"
-
-
-class StarCoder(openllm.LLM["transformers.GPTBigCodeForCausalLM", "transformers.GPT2TokenizerFast"]):
- __openllm_internal__ = True
-
- def llm_post_init(self):
- self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
-
- @property
- def import_kwargs(self):
- model_kwds = {
- "device_map": "auto" if torch.cuda.is_available() and torch.cuda.device_count() > 1 else None,
- "torch_dtype": torch.float16 if torch.cuda.is_available() else torch.float32,
- }
- tokenizer_kwds = {"padding_side": "left"}
- return model_kwds, tokenizer_kwds
-
- def import_model(
- self,
- model_id: str,
- tag: bentoml.Tag,
- *model_args: t.Any,
- tokenizer_kwds: dict[str, t.Any],
- **attrs: t.Any,
- ) -> bentoml.Model:
- torch_dtype = attrs.pop("torch_dtype", torch.float16)
- device_map = attrs.pop("device_map", "auto")
-
- tokenizer = transformers.AutoTokenizer.from_pretrained(model_id, **tokenizer_kwds)
- tokenizer.add_special_tokens(
- {
- "additional_special_tokens": [EOD, FIM_PREFIX, FIM_MIDDLE, FIM_SUFFIX, FIM_PAD],
- "pad_token": EOD,
- }
- )
-
- model = transformers.AutoModelForCausalLM.from_pretrained(
- model_id, torch_dtype=torch_dtype, device_map=device_map, **attrs
- )
- try:
- return bentoml.transformers.save_model(tag, model, custom_objects={"tokenizer": tokenizer})
- finally:
- # NOTE: We need to free the cache after saving here so that we can load it back later on.
- torch.cuda.empty_cache()
-
- def sanitize_parameters(
- self,
- prompt: str,
- temperature: float | None = None,
- top_p: float | None = None,
- max_new_tokens: int | None = None,
- repetition_penalty: float | None = None,
- **attrs: t.Any,
- ) -> tuple[str, dict[str, t.Any], dict[str, t.Any]]:
- fim_mode = FIM_INDICATOR in prompt
- prefix, suffix = None, None
- if fim_mode:
- try:
- prefix, suffix = prompt.split(FIM_INDICATOR)
- except Exception as err:
- logger.error("Error while processing prompt with FIM mode:\n", exc_info=err)
- raise ValueError(f"Only one {FIM_INDICATOR} allowed in prompt") from err
- prompt_text = f"{FIM_PREFIX}{prefix}{FIM_SUFFIX}{suffix}{FIM_MIDDLE}"
- else:
- prompt_text = prompt
-
- generation_config = {
- "temperature": temperature,
- "top_p": top_p,
- "max_new_tokens": max_new_tokens,
- "repetition_penalty": repetition_penalty,
- # XXX: This value is currently a hack, need more investigate why the
- # default starcoder doesn't include the same value as santacoder EOD
- "pad_token_id": 49152,
- **attrs,
- }
-
- return prompt_text, generation_config, {}
-
- def postprocess_generate(self, prompt: str, generation_result: t.Sequence[str], **_: t.Any) -> str:
- return generation_result[0]
-
- def generate(self, prompt: str, **attrs: t.Any) -> list[str]:
- with torch.inference_mode():
- inputs = t.cast("torch.Tensor", self.tokenizer.encode(prompt, return_tensors="pt")).to(self.device)
- result_tensor = self.model.generate(
- inputs,
- do_sample=True,
- pad_token_id=self.tokenizer.eos_token_id,
- # eos_token_id=self.tokenizer.convert_tokens_to_ids("<|end|>"), # NOTE: this is for finetuning starcoder
- generation_config=self.config.model_construct_env(**attrs).to_generation_config(),
- )
- # TODO: We will probably want to return the tokenizer here so that we can manually process this
- # return (skip_special_tokens=False, clean_up_tokenization_spaces=False))
- return self.tokenizer.batch_decode(
- result_tensor[0],
- skip_special_tokens=True,
- clean_up_tokenization_spaces=True,
- )
-
- def generate_one(
- self, prompt: str, stop: list[str], **preprocess_generate_kwds: t.Any
- ) -> list[dict[t.Literal["generated_text"], str]]:
- max_new_tokens = preprocess_generate_kwds.pop("max_new_tokens", 200)
- encoded_inputs = self.tokenizer(prompt, return_tensors="pt").to(self.device)
- src_len = encoded_inputs["input_ids"].shape[1]
- stopping_criteria = preprocess_generate_kwds.pop("stopping_criteria", transformers.StoppingCriteriaList([]))
- stopping_criteria.append(StopSequenceCriteria(stop, self.tokenizer))
- outputs = self.model.generate(
- encoded_inputs["input_ids"], max_new_tokens=max_new_tokens, stopping_criteria=stopping_criteria
- )
-
- result = self.tokenizer.decode(outputs[0].tolist()[src_len:])
- # Inference API returns the stop sequence
- for stop_seq in stop:
- if result.endswith(stop_seq):
- result = result[: -len(stop_seq)]
- return [{"generated_text": result}]
diff --git a/commune/modules/archive/openllm/src/openllm/playground/README.md b/commune/modules/archive/openllm/src/openllm/playground/README.md
deleted file mode 100644
index 73a061cf6..000000000
--- a/commune/modules/archive/openllm/src/openllm/playground/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-This folder represents a playground and source of truth for a features
-development around OpenLLM
-
-```bash
-openllm playground
-```
-
-## Usage for developing this module
-
-Write a python script that can be used by `jupytext` to convert it to a jupyter
-notebook via `openllm playground`
-
-Make sure to add the new file and its documentation into
-[`_meta.yml`](./_meta.yml).
diff --git a/commune/modules/archive/openllm/src/openllm/playground/__init__.py b/commune/modules/archive/openllm/src/openllm/playground/__init__.py
deleted file mode 100644
index 3a2faba50..000000000
--- a/commune/modules/archive/openllm/src/openllm/playground/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
diff --git a/commune/modules/archive/openllm/src/openllm/playground/_meta.yml b/commune/modules/archive/openllm/src/openllm/playground/_meta.yml
deleted file mode 100644
index 72b44c5c7..000000000
--- a/commune/modules/archive/openllm/src/openllm/playground/_meta.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-features:
- description: |
- ## General introduction to OpenLLM.
-
- This script will demo a few features from OpenLLM:
-
- - Usage of Auto class abstraction and run prediction with `generate`
- - Ability to send per-requests parameters
- - Runner integration with BentoML
-opt_tuned:
- description: |
- ## Fine tuning OPT
-
- This script demonstrate how one can easily fine tune OPT
- with [LoRa](https://arxiv.org/abs/2106.09685) and in int8 with bitsandbytes.
-
- It is based on one of the Peft examples fine tuning script.
- It requires at least one GPU to be available, so make sure to have it.
-falcon_tuned:
- description: |
- ## Fine tuning Falcon
-
- This script demonstrate how one can fine tune Falcon using [QLoRa](https://arxiv.org/pdf/2305.14314.pdf),
- [trl](https://github.com/lvwerra/trl).
-
- It is trained using OpenAssistant's Guanaco [dataset](https://huggingface.co/datasets/timdettmers/openassistant-guanaco)
-
- It requires at least one GPU to be available, so make sure to have it.
diff --git a/commune/modules/archive/openllm/src/openllm/playground/falcon_tuned.py b/commune/modules/archive/openllm/src/openllm/playground/falcon_tuned.py
deleted file mode 100644
index 18cef46fa..000000000
--- a/commune/modules/archive/openllm/src/openllm/playground/falcon_tuned.py
+++ /dev/null
@@ -1,117 +0,0 @@
-from __future__ import annotations
-
-import dataclasses
-import logging
-import os
-import sys
-import typing as t
-
-import torch
-
-# import openllm here for OPENLLMDEVDEBUG
-import openllm
-import transformers
-
-
-openllm.utils.configure_logging()
-
-logger = logging.getLogger(__name__)
-
-if len(openllm.utils.gpu_count()) < 1:
- raise RuntimeError("This script can only be run with system that GPU is available.")
-
-_deps = ["trl", '"openllm[fine-tune]"']
-
-if openllm.utils.DEBUG:
- logger.info("Installing dependencies to run this script: %s", _deps)
-
- if os.system(f"pip install -U {' '.join(_deps)}") != 0:
- raise SystemExit(1)
-
-from datasets import load_dataset
-from trl import SFTTrainer
-
-
-DEFAULT_MODEL_ID = "ybelkada/falcon-7b-sharded-bf16"
-DATASET_NAME = "timdettmers/openassistant-guanaco"
-
-
-@dataclasses.dataclass
-class TrainingArguments:
- per_device_train_batch_size: int = dataclasses.field(default=4)
- gradient_accumulation_steps: int = dataclasses.field(default=4)
- optim: str = dataclasses.field(default="paged_adamw_32bit")
- save_steps: int = dataclasses.field(default=10)
- warmup_steps: int = dataclasses.field(default=10)
- max_steps: int = dataclasses.field(default=500)
- logging_steps: int = dataclasses.field(default=10)
- learning_rate: float = dataclasses.field(default=2e-4)
- max_grad_norm: float = dataclasses.field(default=0.3)
- warmup_ratio: float = dataclasses.field(default=0.03)
- fp16: bool = dataclasses.field(default=True)
- group_by_length: bool = dataclasses.field(default=True)
- lr_scheduler_type: str = dataclasses.field(default="constant")
- output_dir: str = dataclasses.field(default=os.path.join(os.getcwd(), "outputs", "falcon"))
-
-
-@dataclasses.dataclass
-class ModelArguments:
- model_id: str = dataclasses.field(default=DEFAULT_MODEL_ID)
- max_sequence_length: int = dataclasses.field(default=512)
-
-
-parser = transformers.HfArgumentParser((ModelArguments, TrainingArguments))
-if len(sys.argv) == 2 and sys.argv[1].endswith(".json"):
- # If we pass only one argument to the script and it's the path to a json file,
- # let's parse it to get our arguments.
- model_args, training_args = parser.parse_json_file(json_file=os.path.abspath(sys.argv[1]))
-else:
- model_args, training_args = t.cast(
- t.Tuple[ModelArguments, TrainingArguments], parser.parse_args_into_dataclasses()
- )
-
-model, tokenizer = openllm.AutoLLM.for_model(
- "falcon",
- model_id=model_args.model_id,
- quantize="int4",
- bnb_4bit_quant_type="nf4",
- bnb_4bit_compute_dtype=torch.float16,
- ensure_available=True,
-).prepare_for_training(
- adapter_type="lora",
- lora_alpha=16,
- lora_dropout=0.1,
- r=16,
- bias="none",
- target_modules=[
- "query_key_value",
- "dense",
- "dense_h_to_4h",
- "dense_4h_to_h",
- ],
-)
-model.config.use_cache = False
-tokenizer.pad_token = tokenizer.eos_token
-
-dataset = load_dataset(DATASET_NAME, split="train")
-
-trainer = SFTTrainer(
- model=model,
- train_dataset=dataset,
- dataset_text_field="text",
- max_seq_length=model_args.max_sequence_length,
- tokenizer=tokenizer,
- args=dataclasses.replace(
- transformers.TrainingArguments(training_args.output_dir),
- **dataclasses.asdict(training_args),
- ),
-)
-
-# upcast layernorm in float32 for more stable training
-for name, module in trainer.model.named_modules():
- if "norm" in name:
- module = module.to(torch.float32)
-
-trainer.train()
-
-model.save_pretrained(os.path.join(training_args.output_dir, "lora"))
diff --git a/commune/modules/archive/openllm/src/openllm/playground/features.py b/commune/modules/archive/openllm/src/openllm/playground/features.py
deleted file mode 100644
index 593223979..000000000
--- a/commune/modules/archive/openllm/src/openllm/playground/features.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from __future__ import annotations
-
-import argparse
-import logging
-import typing as t
-
-import openllm
-
-
-openllm.utils.configure_logging()
-
-logger = logging.getLogger(__name__)
-
-MAX_NEW_TOKENS = 384
-
-Q = "Answer the following question, step by step:\n{q}\nA:"
-question = "What is the meaning of life?"
-
-
-def main() -> int:
- parser = argparse.ArgumentParser()
- parser.add_argument("question", default=question)
-
- if openllm.utils.in_notebook():
- args = parser.parse_args(args=[question])
- else:
- args = parser.parse_args()
-
- model = openllm.AutoLLM.for_model("opt", model_id="facebook/opt-2.7b", ensure_available=True)
- prompt = Q.format(q=args.question)
-
- logger.info("-" * 50, "Running with 'generate()'", "-" * 50)
- res = model.generate(prompt, max_new_tokens=MAX_NEW_TOKENS)
- logger.info("=" * 10, "Response:", model.postprocess_generate(prompt, res))
-
- logger.info("-" * 50, "Running with 'generate()' with per-requests argument", "-" * 50)
- res = model.generate(prompt, num_return_sequences=3)
- logger.info("=" * 10, "Response:", model.postprocess_generate(prompt, res))
-
- logger.info("-" * 50, "Using Runner abstraction with runner.generate.run()", "-" * 50)
- r = openllm.Runner("opt", model_id="facebook/opt-350m", init_local=True)
- res = r.generate.run(prompt)
- logger.info("=" * 10, "Response:", r.llm.postprocess_generate(prompt, res))
-
- logger.info("-" * 50, "Using Runner abstraction with runner()", "-" * 50)
- res = r(prompt)
- logger.info("=" * 10, "Response:", r.llm.postprocess_generate(prompt, res))
-
- return 0
-
-
-def _mp_fn(index: t.Any): # noqa # type: ignore
- # For xla_spawn (TPUs)
- main()
-
-
-if openllm.utils.in_notebook():
- main()
-else:
- raise SystemExit(main())
diff --git a/commune/modules/archive/openllm/src/openllm/playground/opt_tuned.py b/commune/modules/archive/openllm/src/openllm/playground/opt_tuned.py
deleted file mode 100644
index a5273b336..000000000
--- a/commune/modules/archive/openllm/src/openllm/playground/opt_tuned.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from __future__ import annotations
-
-import dataclasses
-import logging
-import os
-import sys
-import typing as t
-
-# import openllm here for OPENLLMDEVDEBUG
-import openllm
-import transformers
-
-
-openllm.utils.configure_logging()
-
-logger = logging.getLogger(__name__)
-
-if len(openllm.utils.gpu_count()) < 1:
- raise RuntimeError("This script can only be run with system that GPU is available.")
-
-_deps = ['"openllm[fine-tune]"']
-
-if openllm.utils.DEBUG:
- logger.info("Installing dependencies to run this script: %s", _deps)
-
- if os.system(f"pip install -U {' '.join(_deps)}") != 0:
- raise SystemExit(1)
-
-from datasets import load_dataset
-
-
-if t.TYPE_CHECKING:
- from peft import PeftModel
-
-DEFAULT_MODEL_ID = "facebook/opt-6.7b"
-
-
-def load_trainer(
- model: PeftModel,
- tokenizer: transformers.GPT2TokenizerFast,
- dataset_dict: t.Any,
- training_args: TrainingArguments,
-):
- return transformers.Trainer(
- model=model,
- train_dataset=dataset_dict["train"],
- args=dataclasses.replace(
- transformers.TrainingArguments(training_args.output_dir),
- **dataclasses.asdict(training_args),
- ),
- data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),
- )
-
-
-@dataclasses.dataclass
-class TrainingArguments:
- per_device_train_batch_size: int = dataclasses.field(default=4)
- gradient_accumulation_steps: int = dataclasses.field(default=4)
- warmup_steps: int = dataclasses.field(default=10)
- max_steps: int = dataclasses.field(default=50)
- learning_rate: float = dataclasses.field(default=3e-4)
- fp16: bool = dataclasses.field(default=True)
- logging_steps: int = dataclasses.field(default=1)
- output_dir: str = dataclasses.field(default=os.path.join(os.getcwd(), "outputs", "opt"))
-
-
-@dataclasses.dataclass
-class ModelArguments:
- model_id: str = dataclasses.field(default=DEFAULT_MODEL_ID)
-
-
-parser = transformers.HfArgumentParser((ModelArguments, TrainingArguments))
-if len(sys.argv) == 2 and sys.argv[1].endswith(".json"):
- # If we pass only one argument to the script and it's the path to a json file,
- # let's parse it to get our arguments.
- model_args, training_args = parser.parse_json_file(json_file=os.path.abspath(sys.argv[1]))
-else:
- model_args, training_args = t.cast(
- t.Tuple[ModelArguments, TrainingArguments], parser.parse_args_into_dataclasses()
- )
-
-
-model, tokenizer = openllm.AutoLLM.for_model(
- "opt",
- model_id=model_args.model_id,
- quantize="int8",
- ensure_available=True,
-).prepare_for_training(
- adapter_type="lora",
- r=16,
- lora_alpha=32,
- target_modules=["q_proj", "v_proj"],
- lora_dropout=0.05,
- bias="none",
-)
-
-# ft on english_quotes
-data = load_dataset("Abirate/english_quotes")
-data = data.map(lambda samples: tokenizer(samples["quote"]), batched=True)
-
-trainer = load_trainer(model, tokenizer, data, training_args)
-model.config.use_cache = False # silence just for warning, reenable for inference later
-
-trainer.train()
-
-model.save_pretrained(os.path.join(training_args.output_dir, "lora"))
diff --git a/commune/modules/archive/openllm/src/openllm/tests.py b/commune/modules/archive/openllm/src/openllm/tests.py
deleted file mode 100644
index 201d68041..000000000
--- a/commune/modules/archive/openllm/src/openllm/tests.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from .utils import is_flax_available
-from .utils import is_tf_available
-from .utils import is_torch_available
-
-
-try:
- import pytest
-except ImportError:
- raise ImportError("You need to install pytest to use 'openllm.tests' utilities: 'pip install pytest'")
-
-
-def require_tf(f: t.Callable[..., t.Any]):
- return pytest.mark.skipif(not is_tf_available(), reason="requires TensorFlow")(f)
-
-
-def require_flax(f: t.Callable[..., t.Any]):
- return pytest.mark.skipif(not is_flax_available(), reason="requires Flax")(f)
-
-
-def require_torch(f: t.Callable[..., t.Any]):
- return pytest.mark.skipif(not is_torch_available(), reason="requires PyTorch")(f)
diff --git a/commune/modules/archive/openllm/src/openllm/utils/__init__.py b/commune/modules/archive/openllm/src/openllm/utils/__init__.py
deleted file mode 100644
index 9830e96c0..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/__init__.py
+++ /dev/null
@@ -1,234 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-Utilities function for OpenLLM. User can import these function for convenience, but
-we won't ensure backward compatibility for these functions. So use with caution.
-"""
-from __future__ import annotations as _annotations
-
-import functools
-import logging
-import logging.config
-import os
-import sys
-import types
-import typing as t
-
-from bentoml._internal.configuration import get_debug_mode
-from bentoml._internal.configuration import get_quiet_mode
-from bentoml._internal.configuration import set_debug_mode
-from bentoml._internal.configuration import set_quiet_mode
-from bentoml._internal.log import CLI_LOGGING_CONFIG as _CLI_LOGGING_CONFIG
-from bentoml._internal.types import LazyType
-from bentoml._internal.utils import LazyLoader
-from bentoml._internal.utils import bentoml_cattr
-from bentoml._internal.utils import copy_file_to_fs_folder
-from bentoml._internal.utils import first_not_none
-from bentoml._internal.utils import pkg
-from bentoml._internal.utils import reserve_free_port
-from bentoml._internal.utils import resolve_user_filepath
-
-from .lazy import LazyModule
-
-
-logger = logging.getLogger(__name__)
-
-try:
- from typing import GenericAlias as _TypingGenericAlias # type: ignore
-except ImportError:
- # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on)
- _TypingGenericAlias = ()
-
-if sys.version_info < (3, 10):
- _WithArgsTypes = (_TypingGenericAlias,)
-else:
- _WithArgsTypes: t.Any = (
- t._GenericAlias, # type: ignore (_GenericAlias is the actual GenericAlias implementation)
- types.GenericAlias,
- types.UnionType,
- )
-
-
-def lenient_issubclass(cls: t.Any, class_or_tuple: type[t.Any] | tuple[type[t.Any], ...] | None) -> bool:
- try:
- return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type]
- except TypeError:
- if isinstance(cls, _WithArgsTypes):
- return False
- raise
-
-
-def gpu_count() -> tuple[int, ...]:
- from bentoml._internal.resource import NvidiaGpuResource
-
- return tuple(NvidiaGpuResource.from_system())
-
-
-# equivocal setattr to save one lookup per assignment
-_object_setattr = object.__setattr__
-
-
-def non_intrusive_setattr(obj: t.Any, name: str, value: t.Any) -> None:
- """This makes sure that we don't overwrite any existing attributes on the object"""
- _setattr = functools.partial(setattr, obj) if isinstance(obj, type) else _object_setattr.__get__(obj)
-
- if not hasattr(obj, name):
- _setattr(name, value)
-
-
-DEBUG = sys.flags.dev_mode or (not sys.flags.ignore_environment and bool(os.environ.get("OPENLLMDEVDEBUG")))
-
-
-_LOGGING_CONFIG = _CLI_LOGGING_CONFIG.copy()
-_LOGGING_CONFIG["loggers"].update(
- {
- "openllm": {
- "level": logging.INFO,
- "handlers": ["bentomlhandler", "defaulthandler"],
- "propagate": False,
- }
- }
-)
-
-
-def configure_logging() -> None:
- """Configure logging for OpenLLM. Behaves similar to how BentoML loggers
- are being configured."""
- if get_quiet_mode():
- _LOGGING_CONFIG["loggers"]["openllm"]["level"] = logging.ERROR
- _LOGGING_CONFIG["loggers"]["bentoml"]["level"] = logging.ERROR
- _LOGGING_CONFIG["root"]["level"] = logging.ERROR
- elif get_debug_mode() or DEBUG:
- _LOGGING_CONFIG["loggers"]["openllm"]["level"] = logging.DEBUG
- _LOGGING_CONFIG["loggers"]["bentoml"]["level"] = logging.DEBUG
- _LOGGING_CONFIG["root"]["level"] = logging.DEBUG
- else:
- _LOGGING_CONFIG["loggers"]["openllm"]["level"] = logging.INFO
- _LOGGING_CONFIG["loggers"]["bentoml"]["level"] = logging.INFO
- _LOGGING_CONFIG["root"]["level"] = logging.INFO
-
- logging.config.dictConfig(_LOGGING_CONFIG)
-
-@functools.lru_cache(maxsize=1)
-def in_notebook() -> bool:
- try:
- from IPython.core.getipython import get_ipython
-
- if "IPKernelApp" not in get_ipython().config: # pragma: no cover
- return False
- except ImportError:
- return False
- except AttributeError:
- return False
- return True
-
-
-# NOTE: The set marks contains a set of modules name
-# that are available above and are whitelisted
-# to be included in the extra_objects map.
-_whitelist_modules = {"pkg"}
-
-# XXX: define all classes, functions import above this line
-# since _extras will be the locals() import from this file.
-_extras: dict[str, t.Any] = {
- k: v
- for k, v in locals().items()
- if k in _whitelist_modules or (not isinstance(v, types.ModuleType) and not k.startswith("_"))
-}
-
-_extras["__openllm_migration__"] = {"ModelEnv": "EnvVarMixin"}
-
-_import_structure = {
- "analytics": [],
- "codegen": [],
- "dantic": [],
- "representation": ["ReprMixin"],
- "import_utils": [
- "OPTIONAL_DEPENDENCIES",
- "ENV_VARS_TRUE_VALUES",
- "DummyMetaclass",
- "EnvVarMixin",
- "requires_dependencies",
- "is_cpm_kernels_available",
- "is_einops_available",
- "is_flax_available",
- "is_tf_available",
- "is_torch_available",
- "is_bitsandbytes_available",
- "is_peft_available",
- "is_datasets_available",
- "is_transformers_supports_kbit",
- "is_transformers_supports_agent",
- "is_jupyter_available",
- "is_jupytext_available",
- "is_notebook_available",
- "is_triton_available",
- "require_backends",
- ],
-}
-
-if t.TYPE_CHECKING:
- # NOTE: The following exports useful utils from bentoml
- from . import LazyLoader as LazyLoader
- from . import LazyType as LazyType
- from . import analytics as analytics
- from . import bentoml_cattr as bentoml_cattr
- from . import codegen as codegen
- from . import configure_logging as configure_logging
- from . import copy_file_to_fs_folder as copy_file_to_fs_folder
- from . import dantic as dantic
- from . import first_not_none as first_not_none
- from . import get_debug_mode as get_debug_mode
- from . import get_quiet_mode as get_quiet_mode
- from . import gpu_count as gpu_count
- from . import lenient_issubclass as lenient_issubclass
- from . import non_intrusive_setattr as non_intrusive_setattr
- from . import pkg as pkg
- from . import reserve_free_port as reserve_free_port
- from . import resolve_user_filepath as resolve_user_filepath
- from . import set_debug_mode as set_debug_mode
- from . import set_quiet_mode as set_quiet_mode
- from . import in_notebook as in_notebook
- from .import_utils import ENV_VARS_TRUE_VALUES as ENV_VARS_TRUE_VALUES
- from .import_utils import OPTIONAL_DEPENDENCIES as OPTIONAL_DEPENDENCIES
- from .import_utils import DummyMetaclass as DummyMetaclass
- from .import_utils import EnvVarMixin as EnvVarMixin
- from .import_utils import is_bitsandbytes_available as is_bitsandbytes_available
- from .import_utils import is_cpm_kernels_available as is_cpm_kernels_available
- from .import_utils import is_datasets_available as is_datasets_available
- from .import_utils import is_einops_available as is_einops_available
- from .import_utils import is_flax_available as is_flax_available
- from .import_utils import is_peft_available as is_peft_available
- from .import_utils import is_tf_available as is_tf_available
- from .import_utils import is_torch_available as is_torch_available
- from .import_utils import is_transformers_supports_agent as is_transformers_supports_agent
- from .import_utils import is_transformers_supports_kbit as is_transformers_supports_kbit
- from .import_utils import is_triton_available as is_triton_available
- from .import_utils import require_backends as require_backends
- from .import_utils import requires_dependencies as requires_dependencies
- from .import_utils import is_jupyter_available as is_jupyter_available
- from .import_utils import is_jupytext_available as is_jupytext_available
- from .import_utils import is_notebook_available as is_notebook_available
- from .lazy import LazyModule as LazyModule
- from .representation import ReprMixin as ReprMixin
-else:
- import sys
-
- sys.modules[__name__] = LazyModule(
- __name__,
- globals()["__file__"],
- _import_structure,
- module_spec=__spec__,
- extra_objects=_extras,
- )
diff --git a/commune/modules/archive/openllm/src/openllm/utils/analytics.py b/commune/modules/archive/openllm/src/openllm/utils/analytics.py
deleted file mode 100644
index a7e311c6c..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/analytics.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-Telemetry related for OpenLLM tracking.
-
-Users can disable this with OPENLLM_DO_NOT_TRACK envvar.
-"""
-from __future__ import annotations
-
-import contextlib
-import functools
-import os
-import typing as t
-
-import attr
-
-from bentoml._internal.utils import analytics as _internal_analytics
-from bentoml._internal.utils.analytics import usage_stats as _internal_usage
-
-
-if t.TYPE_CHECKING:
- import openllm
-
-from ..__about__ import __version__
-
-
-ENV_VARS_TRUE_VALUES = {"1", "ON", "YES", "TRUE"}
-
-# This variable is a proxy that will control BENTOML_DO_NOT_TRACK
-OPENLLM_DO_NOT_TRACK = "OPENLLM_DO_NOT_TRACK"
-
-DO_NOT_TRACK = os.environ.get(OPENLLM_DO_NOT_TRACK, str(False)).upper()
-
-
-@functools.lru_cache(maxsize=1)
-def do_not_track() -> bool:
- return DO_NOT_TRACK in ENV_VARS_TRUE_VALUES
-
-
-@_internal_usage.silent
-def track(event_properties: _internal_analytics.schemas.EventMeta):
- if do_not_track():
- return
- _internal_analytics.track(event_properties)
-
-
-@contextlib.contextmanager
-def set_bentoml_tracking():
- original_value = os.environ.pop(_internal_analytics.BENTOML_DO_NOT_TRACK, str(False))
- try:
- os.environ[_internal_analytics.BENTOML_DO_NOT_TRACK] = str(do_not_track())
- yield
- finally:
- os.environ[_internal_analytics.BENTOML_DO_NOT_TRACK] = original_value
-
-
-@attr.define
-class OpenllmCliEvent(_internal_analytics.schemas.EventMeta):
- cmd_group: str
- cmd_name: str
- openllm_version: str = __version__
-
- # NOTE: reserved for the do_not_track logics
- duration_in_ms: t.Any = attr.field(default=None)
- error_type: str = attr.field(default=None)
- return_code: int = attr.field(default=None)
-
-
-@attr.define
-class StartInitEvent(_internal_analytics.schemas.EventMeta):
- model_name: str
- llm_config: t.Dict[str, t.Any] = attr.field(default=None)
-
- @staticmethod
- def handler(llm_config: openllm.LLMConfig) -> StartInitEvent:
- return StartInitEvent(model_name=llm_config["model_name"], llm_config=llm_config.model_dump())
-
-
-def track_start_init(
- llm_config: openllm.LLMConfig,
-):
- if do_not_track():
- return
- track(StartInitEvent.handler(llm_config))
diff --git a/commune/modules/archive/openllm/src/openllm/utils/codegen.py b/commune/modules/archive/openllm/src/openllm/utils/codegen.py
deleted file mode 100644
index 6d9d130fd..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/codegen.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import logging
-import os
-import string
-import typing as t
-from pathlib import Path
-
-import orjson
-
-
-if t.TYPE_CHECKING:
- from fs.base import FS
-
- import openllm
-
- DictStrAny = dict[str, t.Any]
-
- from attr import _make_method
-else:
- # NOTE: Using internal API from attr here, since we are actually
- # allowing subclass of openllm.LLMConfig to become 'attrs'-ish
- from attr._make import _make_method
-
- DictStrAny = dict
-
-_T = t.TypeVar("_T", bound=t.Callable[..., t.Any])
-
-logger = logging.getLogger(__name__)
-
-OPENLLM_SERVING = "# openllm: serving"
-OPENLLM_MODEL_NAME = "# openllm: model name"
-OPENLLM_MODEL_ID = "# openllm: model id"
-OPENLLM_MODEL_ADAPTER_MAP = "# openllm: model adapter map"
-
-
-class ModelNameFormatter(string.Formatter):
- model_keyword: t.LiteralString = "__model_name__"
-
- def __init__(self, model_name: str):
- super().__init__()
- self.model_name = model_name
-
- def vformat(self, format_string: str) -> str:
- return super().vformat(format_string, (), {self.model_keyword: self.model_name})
-
- def can_format(self, value: str) -> bool:
- try:
- self.parse(value)
- return True
- except ValueError:
- return False
-
-
-class ModelIdFormatter(ModelNameFormatter):
- model_keyword: t.LiteralString = "__model_id__"
-
-
-class ModelAdapterMapFormatter(ModelNameFormatter):
- model_keyword: t.LiteralString = "__model_adapter_map__"
-
-
-_service_file = Path(__file__).parent.parent / "_service.py"
-
-
-def write_service(llm: openllm.LLM[t.Any, t.Any], adapter_map: dict[str, str | None] | None, llm_fs: FS):
- from . import DEBUG
-
- model_name = llm.config["model_name"]
-
- logger.debug("Generating service for %s", model_name)
-
- with open(_service_file.__fspath__(), "r") as f:
- src_contents = f.readlines()
-
- # modify with model name
- for it in src_contents:
- if OPENLLM_MODEL_NAME in it:
- src_contents[src_contents.index(it)] = (
- ModelNameFormatter(model_name).vformat(it)[: -(len(OPENLLM_MODEL_NAME) + 3)] + "\n"
- )
- elif OPENLLM_MODEL_ADAPTER_MAP in it:
- src_contents[src_contents.index(it)] = (
- ModelAdapterMapFormatter(orjson.dumps(adapter_map).decode()).vformat(it)[
- : -(len(OPENLLM_MODEL_ADAPTER_MAP) + 3)
- ]
- + "\n"
- )
-
- script = f"# GENERATED BY 'openllm build {model_name}'. DO NOT EDIT\n\n" + "".join(src_contents)
-
- if DEBUG:
- logger.info("Generated script:\n%s", script)
-
- llm_fs.writetext(llm.config["service_name"], script)
-
-
-# NOTE: The following ins extracted from attrs internal APIs
-
-# sentinel object for unequivocal object() getattr
-_sentinel = object()
-
-
-def has_own_attribute(cls: type[t.Any], attrib_name: t.Any):
- """
- Check whether *cls* defines *attrib_name* (and doesn't just inherit it).
- """
- attr = getattr(cls, attrib_name, _sentinel)
- if attr is _sentinel:
- return False
-
- for base_cls in cls.__mro__[1:]:
- a = getattr(base_cls, attrib_name, None)
- if attr is a:
- return False
-
- return True
-
-
-def get_annotations(cls: type[t.Any]) -> DictStrAny:
- """
- Get annotations for *cls*.
- """
- if has_own_attribute(cls, "__annotations__"):
- return cls.__annotations__
-
- return DictStrAny()
-
-
-_classvar_prefixes = (
- "typing.ClassVar",
- "t.ClassVar",
- "ClassVar",
- "typing_extensions.ClassVar",
-)
-
-
-def is_class_var(annot: str | t.Any) -> bool:
- """
- Check whether *annot* is a typing.ClassVar.
-
- The string comparison hack is used to avoid evaluating all string
- annotations which would put attrs-based classes at a performance
- disadvantage compared to plain old classes.
- """
- annot = str(annot)
-
- # Annotation can be quoted.
- if annot.startswith(("'", '"')) and annot.endswith(("'", '"')):
- annot = annot[1:-1]
-
- return annot.startswith(_classvar_prefixes)
-
-
-def add_method_dunders(cls: type[t.Any], method_or_cls: _T, _overwrite_doc: str | None = None) -> _T:
- """
- Add __module__ and __qualname__ to a *method* if possible.
- """
- try:
- method_or_cls.__module__ = cls.__module__
- except AttributeError:
- pass
-
- try:
- method_or_cls.__qualname__ = ".".join((cls.__qualname__, method_or_cls.__name__))
- except AttributeError:
- pass
-
- try:
- method_or_cls.__doc__ = (
- _overwrite_doc or "Method or class generated by LLMConfig for class " f"{cls.__qualname__}."
- )
- except AttributeError:
- pass
-
- return method_or_cls
-
-
-def generate_unique_filename(cls: type[t.Any], func_name: str):
- return f"<{cls.__name__} generated {func_name} {cls.__module__}." f"{getattr(cls, '__qualname__', cls.__name__)}>"
-
-
-def generate_function(
- typ: type[t.Any],
- func_name: str,
- lines: list[str] | None,
- args: tuple[str, ...] | None,
- globs: dict[str, t.Any],
- annotations: dict[str, t.Any] | None = None,
-):
- from . import DEBUG
-
- script = "def %s(%s):\n %s\n" % (
- func_name,
- ", ".join(args) if args is not None else "",
- "\n ".join(lines) if lines else "pass",
- )
- meth = _make_method(func_name, script, generate_unique_filename(typ, func_name), globs)
- if annotations:
- meth.__annotations__ = annotations
-
- if DEBUG and int(os.environ.get("OPENLLMDEVDEBUG", str(0))) > 3:
- logger.info("Generated script for %s:\n\n%s", typ, script)
-
- return meth
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dantic.py b/commune/modules/archive/openllm/src/openllm/utils/dantic.py
deleted file mode 100644
index 9190ed4ab..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dantic.py
+++ /dev/null
@@ -1,457 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""A shim provides usable transition from pydantic to attrs."""
-
-from __future__ import annotations
-
-import functools
-import importlib
-import os
-import typing as t
-from enum import Enum
-
-import attr
-import click
-import click_option_group as cog
-import inflection
-import orjson
-from click import ParamType
-
-import openllm
-
-
-# NOTE: We need to do this so that overload can register
-# correct overloads to typing registry
-if hasattr(t, "get_overloads"):
- from typing import overload
-else:
- from typing_extensions import overload
-
-if t.TYPE_CHECKING:
- from attr import _ValidatorType
-
- from .._types import ClickFunctionWrapper
- from .._types import F
- from .._types import O_co
- from .._types import P
-
-_T = t.TypeVar("_T")
-
-
-@overload
-def attrs_to_options(
- name: str,
- field: attr.Attribute[t.Any],
- model_name: str,
- typ: type[t.Any] | None = None,
- suffix_generation: bool = False,
-) -> F[..., F[..., openllm.LLMConfig]]:
- ...
-
-
-@overload
-def attrs_to_options( # type: ignore (overlapping overload)
- name: str,
- field: attr.Attribute[O_co],
- model_name: str,
- typ: type[t.Any] | None = None,
- suffix_generation: bool = False,
-) -> F[..., F[P, O_co]]:
- ...
-
-
-def attrs_to_options(
- name: str,
- field: attr.Attribute[t.Any],
- model_name: str,
- typ: type[t.Any] | None = None,
- suffix_generation: bool = False,
-) -> t.Callable[..., ClickFunctionWrapper[..., t.Any]]:
- # TODO: support parsing nested attrs class and Union
- envvar = field.metadata["env"]
- dasherized = inflection.dasherize(name)
- underscored = inflection.underscore(name)
-
- if typ in (None, attr.NOTHING):
- typ = field.type
-
- full_option_name = f"--{dasherized}"
- if field.type is bool:
- full_option_name += f"/--no-{dasherized}"
- if suffix_generation:
- identifier = f"{model_name}_generation_{underscored}"
- else:
- identifier = f"{model_name}_{underscored}"
-
- return cog.optgroup.option(
- identifier,
- full_option_name,
- type=parse_type(typ),
- required=field.default is attr.NOTHING,
- default=field.default if field.default not in (attr.NOTHING, None) else None,
- show_default=True,
- multiple=allows_multiple(typ),
- help=field.metadata.get("description", "(No description provided)"),
- show_envvar=True,
- envvar=envvar,
- )
-
-
-def env_converter(value: t.Any, env: str | None = None) -> t.Any:
- if env is not None:
- value = os.environ.get(env, value)
- if value is not None and isinstance(value, str):
- try:
- return orjson.loads(value.lower())
- except orjson.JSONDecodeError as err:
- raise RuntimeError(f"Failed to parse ({value!r}) from '{env}': {err}")
- return value
-
-
-def Field(
- default: t.Any = None,
- *,
- ge: int | float | None = None,
- le: int | float | None = None,
- validator: _ValidatorType[_T] | None = None,
- description: str | None = None,
- env: str | None = None,
- auto_default: bool = False,
- use_default_converter: bool = True,
- **attrs: t.Any,
-):
- """A decorator that extends attr.field with additional arguments, which provides the same
- interface as pydantic's Field.
-
- By default, if both validator and ge are provided, then then ge will be
- piped into first, then all of the other validator will be run afterwards.
-
- Args:
- ge: Greater than or equal to. Defaults to None.
- description: the documentation for the field. Defaults to None.
- env: the environment variable to read from. Defaults to None.
- auto_default: a bool indicating whether to use the default value as the environment.
- Defaults to False. If set to True, the behaviour of this Field will also depends
- on kw_only. If kw_only=True, the this field will become 'Required' and the default
- value is omitted. If kw_only=False, then the default value will be used as before.
- use_default_converter: a bool indicating whether to use the default converter. Defaults
- to True. If set to False, then the default converter will not be used.
- The default converter converts a given value from the environment variable
- for this given Field.
- **kwargs: The rest of the arguments are passed to attr.field
- """
- metadata = attrs.pop("metadata", {})
- if description is None:
- description = "(No description provided)"
- metadata["description"] = description
- if env is not None:
- metadata["env"] = env
- piped: list[_ValidatorType[t.Any]] = []
-
- converter = attrs.pop("converter", None)
- if use_default_converter:
- converter = functools.partial(env_converter, env=env)
-
- if ge is not None:
- piped.append(attr.validators.ge(ge))
- if le is not None:
- piped.append(attr.validators.le(le))
- if validator is not None:
- piped.append(validator)
-
- if len(piped) == 0:
- _validator = None
- elif len(piped) == 1:
- _validator = piped[0]
- else:
- _validator = attr.validators.and_(*piped)
-
- factory = attrs.pop("factory", None)
- if factory is not None and default is not None:
- raise RuntimeError("'factory' and 'default' are mutually exclusive.")
- # NOTE: the behaviour of this is we will respect factory over the default
- if factory is not None:
- attrs["factory"] = factory
- else:
- attrs["default"] = default
-
- kw_only = attrs.pop("kw_only", False)
- if auto_default and kw_only:
- attrs.pop("default")
-
- return attr.field(metadata=metadata, validator=_validator, converter=converter, **attrs)
-
-
-def parse_type(field_type: t.Any) -> ParamType | tuple[ParamType]:
- """Transforms the pydantic field's type into a click-compatible type.
-
- Args:
- field_type: pydantic field type
-
- Returns:
- ParamType: click type equivalent
- """
- from . import lenient_issubclass
-
- assert t.get_origin(field_type) is not t.Union, "Unions are not supported"
- # enumeration strings or other Enum derivatives
- if lenient_issubclass(field_type, Enum):
- return EnumChoice(enum=field_type, case_sensitive=True)
- # literals are enum-like with way less functionality
- if is_literal(field_type):
- return LiteralChoice(enum=field_type, case_sensitive=True)
- # modules, classes, functions
- if is_typing(field_type):
- return ModuleType()
- # entire dictionaries:
- # using a Dict, convert in advance
- if is_mapping(field_type):
- return JsonType()
- # list, List[p], Tuple[p], Set[p] and so on
- if is_container(field_type):
- return parse_container_args(field_type)
- # bytes are not natively supported by click
- if lenient_issubclass(field_type, bytes):
- return BytesType()
- # return the current type: it should be a primitive
- return field_type
-
-
-def is_typing(field_type: type) -> bool:
- """Checks whether the current type is a module-like type.
-
- Args:
- field_type: pydantic field type
-
- Returns:
- bool: true if the type is itself a type
- """
- raw = t.get_origin(field_type)
- if raw is None:
- return False
- if raw is type or raw is t.Type:
- return True
- return False
-
-
-def is_literal(field_type: type) -> bool:
- """Checks whether the given field type is a Literal type or not.
- Literals are weird: isinstance and subclass do not work, so you compare
- the origin with the Literal declaration itself.
-
- Args:
- field_type: current pydantic type
-
- Returns:
- bool: true if Literal type, false otherwise
- """
- origin = t.get_origin(field_type)
- return origin is not None and origin is t.Literal
-
-
-class ModuleType(ParamType):
- name = "module"
-
- def _import_object(self, value: str) -> t.Any:
- module_name, class_name = value.rsplit(".", maxsplit=1)
- assert all(s.isidentifier() for s in module_name.split(".")), f"'{value}' is not a valid module name"
- assert class_name.isidentifier(), f"Variable '{class_name}' is not a valid identifier"
-
- module = importlib.import_module(module_name)
- if class_name:
- try:
- return getattr(module, class_name)
- except AttributeError:
- raise ImportError(f"Module '{module_name}' does not define a '{class_name}' variable.")
- return None
-
- def convert(self, value: str, param: click.Parameter | None, ctx: click.Context | None) -> t.Any:
- try:
- if isinstance(value, str):
- return self._import_object(value)
- return value
- except Exception as exc:
- self.fail(f"'{value}' is not a valid object ({type(exc)}: {str(exc)})", param, ctx)
-
-
-class EnumChoice(click.Choice):
- name = "enum"
-
- def __init__(self, enum: Enum, case_sensitive: bool = False):
- self.mapping = enum
- self.internal_type = enum
- super().__init__([e.name for e in self.mapping], case_sensitive)
-
- def convert(self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None) -> Enum:
- if isinstance(value, self.internal_type):
- return value
- result = super().convert(value, param, ctx)
- if isinstance(result, str):
- result = self.mapping[result]
- return result
-
-
-class LiteralChoice(EnumChoice):
- name = "literal"
-
- def __init__(self, enum: t.LiteralString, case_sensitive: bool = False):
- # expect every literal value to belong to the same primitive type
- values = list(enum.__args__)
- item_type = type(values[0])
- assert all(isinstance(v, item_type) for v in values), f"Field {enum} contains items of different types"
- self.internal_type = item_type
- self.mapping = {str(v): v for v in values}
- super(EnumChoice, self).__init__(list(self.mapping.keys()), case_sensitive)
-
-
-def allows_multiple(field_type: t.Any) -> bool:
- """Checks whether the current type allows for multiple arguments to be provided as input or not.
- For containers, it exploits click's support for lists and such to use the same option multiple times
- to create a complex object: `python run.py --subsets train --subsets test`
- # becomes `subsets: ["train", "test"]`.
- Args:
- field_type (type): pydantic type
-
- Returns:
- bool: true if it's a composite field (lists, containers and so on), false otherwise
- """
- # Early out for mappings, since it's better to deal with them using strings.
- if is_mapping(field_type):
- return False
- # Activate multiple option for (simple) container types
- if is_container(field_type):
- args = parse_container_args(field_type)
- # A non-composite type has a single argument, such as 'List[int]'
- # A composite type has a tuple of arguments, like 'Tuple[str, int, int]'.
- # For the moment, only non-composite types are allowed.
- return not isinstance(args, tuple)
- return False
-
-
-def is_mapping(field_type: type) -> bool:
- """Checks whether this field represents a dictionary or JSON object.
-
- Args:
- field_type (type): pydantic type
-
- Returns:
- bool: true when the field is a dict-like object, false otherwise.
- """
- # Early out for standard containers.
- if openllm.utils.lenient_issubclass(field_type, t.Mapping):
- return True
- # for everything else or when the typing is more complex, check its origin
- origin = t.get_origin(field_type)
- if origin is None:
- return False
- return openllm.utils.lenient_issubclass(origin, t.Mapping)
-
-
-def is_container(field_type: type) -> bool:
- """Checks whether the current type is a container type ('contains' other types), like
- lists and tuples.
-
- Args:
- field_type: pydantic field type
-
- Returns:
- bool: true if a container, false otherwise
- """
- # do not consider strings or byte arrays as containers
- if field_type in (str, bytes):
- return False
- # Early out for standard containers: list, tuple, range
- if openllm.utils.lenient_issubclass(field_type, t.Container):
- return True
- origin = t.get_origin(field_type)
- # Early out for non-typing objects
- if origin is None:
- return False
- return openllm.utils.lenient_issubclass(origin, t.Container)
-
-
-def parse_container_args(field_type: type[t.Any]) -> ParamType | tuple[ParamType]:
- """Parses the arguments inside a container type (lists, tuples and so on).
-
- Args:
- field_type: pydantic field type
-
- Returns:
- ParamType | tuple[ParamType]: single click-compatible type or a tuple
- """
- assert is_container(field_type), "Field type is not a container"
- args = t.get_args(field_type)
- # Early out for untyped containers: standard lists, tuples, List[Any]
- # Use strings when the type is unknown, avoid click's type guessing
- if len(args) == 0:
- return str
- # Early out for homogenous containers: Tuple[int], List[str]
- if len(args) == 1:
- return parse_single_arg(args[0])
- # Early out for homogenous tuples of indefinite length: Tuple[int, ...]
- if len(args) == 2 and args[1] is Ellipsis:
- return parse_single_arg(args[0])
- # Then deal with fixed-length containers: Tuple[str, int, int]
- return tuple(parse_single_arg(arg) for arg in args)
-
-
-def parse_single_arg(arg: type) -> ParamType:
- """Returns the click-compatible type for container origin types.
- In this case, returns string when it's not inferrable, a JSON for mappings
- and the original type itself in every other case (ints, floats and so on).
- Bytes is a special case, not natively handled by click.
-
- Args:
- arg (type): single argument
-
- Returns:
- ParamType: click-compatible type
- """
- # When we don't know the type, we choose 'str'
- if arg is t.Any:
- return str
- # For containers and nested models, we use JSON
- if is_container(arg):
- return JsonType()
- if openllm.utils.lenient_issubclass(arg, bytes):
- return BytesType()
- return arg
-
-
-class BytesType(ParamType):
- name = "bytes"
-
- def convert(self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None) -> t.Any:
- if isinstance(value, bytes):
- return value
- try:
- return str.encode(value)
- except Exception as exc:
- self.fail(f"'{value}' is not a valid string ({str(exc)})", param, ctx)
-
-
-class JsonType(ParamType):
- name = "json"
-
- def __init__(self, should_load: bool = True) -> None:
- super().__init__()
- self.should_load = should_load
-
- def convert(self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None) -> t.Any:
- if openllm.utils.LazyType[t.Mapping[str, str]](t.Mapping).isinstance(value) or not self.should_load:
- return value
- try:
- return orjson.loads(value)
- except orjson.JSONDecodeError as exc:
- self.fail(f"'{value}' is not a valid JSON string ({str(exc)})", param, ctx)
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dummy_flax_objects.py b/commune/modules/archive/openllm/src/openllm/utils/dummy_flax_objects.py
deleted file mode 100644
index 9e2700fa3..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dummy_flax_objects.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from ..utils import DummyMetaclass
-from ..utils import require_backends
-
-
-class FlaxFlanT5(metaclass=DummyMetaclass):
- _backends = ["flax"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["flax"])
-
-
-class FlaxOPT(metaclass=DummyMetaclass):
- _backends = ["flax"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["flax"])
-
-
-class AutoFlaxLLM(metaclass=DummyMetaclass):
- _backends = ["flax"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["flax"])
-
-
-MODEL_FLAX_MAPPING = None
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_cpm_kernels_objects.py b/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_cpm_kernels_objects.py
deleted file mode 100644
index 88ba77fdc..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_cpm_kernels_objects.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from ..utils import DummyMetaclass
-from ..utils import require_backends
-
-
-class ChatGLM(metaclass=DummyMetaclass):
- _backends = ["torch", "cpm_kernels"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch", "cpm_kernels"])
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_einops_objects.py b/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_einops_objects.py
deleted file mode 100644
index 2a5779064..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_einops_objects.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from ..utils import DummyMetaclass
-from ..utils import require_backends
-
-
-class Falcon(metaclass=DummyMetaclass):
- _backends = ["torch", "einops"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch", "einops"])
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_triton_objects.py b/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_triton_objects.py
deleted file mode 100644
index 643b72600..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_and_triton_objects.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from ..utils import DummyMetaclass
-from ..utils import require_backends
-
-
-class MPT(metaclass=DummyMetaclass):
- _backends = ["torch", "triton"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_objects.py b/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_objects.py
deleted file mode 100644
index ff1ce214d..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dummy_pt_objects.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from ..utils import DummyMetaclass
-from ..utils import require_backends
-
-
-class FlanT5(metaclass=DummyMetaclass):
- _backends = ["torch"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
-
-
-class OPT(metaclass=DummyMetaclass):
- _backends = ["torch"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
-
-
-class DollyV2(metaclass=DummyMetaclass):
- _backends = ["torch"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
-
-
-class StarCoder(metaclass=DummyMetaclass):
- _backends = ["torch"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
-
-
-class StableLM(metaclass=DummyMetaclass):
- _backends = ["torch"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
-
-
-class AutoLLM(metaclass=DummyMetaclass):
- _backends = ["torch"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["torch"])
-
-
-MODEL_MAPPING = None
diff --git a/commune/modules/archive/openllm/src/openllm/utils/dummy_tf_objects.py b/commune/modules/archive/openllm/src/openllm/utils/dummy_tf_objects.py
deleted file mode 100644
index 2d0a86511..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/dummy_tf_objects.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-from ..utils import DummyMetaclass
-from ..utils import require_backends
-
-
-class TFFlanT5(metaclass=DummyMetaclass):
- _backends = ["tf"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["tf"])
-
-
-class TFOPT(metaclass=DummyMetaclass):
- _backends = ["tf"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["tf"])
-
-
-class AutoTFLLM(metaclass=DummyMetaclass):
- _backends = ["tf"]
-
- def __init__(self, *args: t.Any, **attrs: t.Any):
- require_backends(self, ["tf"])
-
-
-MODEL_TF_MAPPING = None
diff --git a/commune/modules/archive/openllm/src/openllm/utils/import_utils.py b/commune/modules/archive/openllm/src/openllm/utils/import_utils.py
deleted file mode 100644
index 337844de1..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/import_utils.py
+++ /dev/null
@@ -1,461 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Some imports utils are vendorred from transformers/utils/import_utils.py for performance reasons.
-"""
-from __future__ import annotations
-
-import functools
-import importlib
-import importlib.metadata
-import importlib.util
-import logging
-import os
-import typing as t
-from abc import ABCMeta
-from collections import OrderedDict
-
-import inflection
-from packaging import version
-
-from bentoml._internal.utils import LazyLoader
-from bentoml._internal.utils import pkg
-
-from .representation import ReprMixin
-
-
-# NOTE: We need to do this so that overload can register
-# correct overloads to typing registry
-if hasattr(t, "get_overloads"):
- from typing import overload
-else:
- from typing_extensions import overload
-
-if t.TYPE_CHECKING:
- BackendOrderredDict = OrderedDict[str, tuple[t.Callable[[], bool], str]]
- from .._types import P
-else:
- BackendOrderredDict = OrderedDict
-
-logger = logging.getLogger(__name__)
-
-OPTIONAL_DEPENDENCIES = {
- "fine-tune",
- "flan-t5",
- "mpt",
- "falcon",
- "starcoder",
- "chatglm",
- "openai",
- "agents",
- "playground",
-}
-ENV_VARS_TRUE_VALUES = {"1", "ON", "YES", "TRUE"}
-ENV_VARS_TRUE_AND_AUTO_VALUES = ENV_VARS_TRUE_VALUES.union({"AUTO"})
-
-USE_TF = os.environ.get("USE_TF", "AUTO").upper()
-USE_TORCH = os.environ.get("USE_TORCH", "AUTO").upper()
-USE_JAX = os.environ.get("USE_FLAX", "AUTO").upper()
-
-FORCE_TF_AVAILABLE = os.environ.get("FORCE_TF_AVAILABLE", "AUTO").upper()
-
-
-def _is_package_available(package: str) -> bool:
- _package_available = importlib.util.find_spec(package) is not None
- if _package_available:
- try:
- importlib.metadata.version(package)
- except importlib.metadata.PackageNotFoundError:
- _package_available = False
- return _package_available
-
-
-_torch_available = importlib.util.find_spec("torch") is not None
-_tf_available = importlib.util.find_spec("tensorflow") is not None
-_flax_available = importlib.util.find_spec("jax") is not None and importlib.util.find_spec("flax") is not None
-
-_peft_available = _is_package_available("peft")
-_einops_available = _is_package_available("einops")
-_cpm_kernel_available = _is_package_available("cpm_kernels")
-_bitsandbytes_available = _is_package_available("bitsandbytes")
-_datasets_available = _is_package_available("datasets")
-_triton_available = _is_package_available("triton")
-_jupyter_available = _is_package_available("jupyter")
-_jupytext_available = _is_package_available("jupytext")
-_notebook_available = _is_package_available("notebook")
-
-
-def is_transformers_supports_kbit() -> bool:
- return pkg.pkg_version_info("transformers")[:2] >= (4, 30)
-
-
-def is_transformers_supports_agent() -> bool:
- return pkg.pkg_version_info("transformers")[:2] >= (4, 29)
-
-
-def is_jupyter_available() -> bool:
- return _jupyter_available
-
-def is_jupytext_available() -> bool:
- return _jupytext_available
-
-def is_notebook_available() -> bool:
- return _notebook_available
-
-def is_triton_available() -> bool:
- return _triton_available
-
-
-def is_datasets_available() -> bool:
- return _datasets_available
-
-
-def is_peft_available() -> bool:
- return _peft_available
-
-
-def is_einops_available():
- return _einops_available
-
-
-def is_cpm_kernels_available():
- return _cpm_kernel_available
-
-
-def is_bitsandbytes_available():
- return _bitsandbytes_available
-
-
-def is_torch_available():
- global _torch_available
- if USE_TORCH in ENV_VARS_TRUE_AND_AUTO_VALUES and USE_TF not in ENV_VARS_TRUE_VALUES:
- if _torch_available:
- try:
- importlib.metadata.version("torch")
- except importlib.metadata.PackageNotFoundError:
- _torch_available = False
- else:
- logger.info("Disabling PyTorch because USE_TF is set")
- _torch_available = False
- return _torch_available
-
-
-def is_tf_available():
- global _tf_available
- if FORCE_TF_AVAILABLE in ENV_VARS_TRUE_VALUES:
- _tf_available = True
- else:
- _tf_version = None
- if USE_TF in ENV_VARS_TRUE_AND_AUTO_VALUES and USE_TORCH not in ENV_VARS_TRUE_VALUES:
- if _tf_available:
- candidates = (
- "tensorflow",
- "tensorflow-cpu",
- "tensorflow-gpu",
- "tf-nightly",
- "tf-nightly-cpu",
- "tf-nightly-gpu",
- "intel-tensorflow",
- "intel-tensorflow-avx512",
- "tensorflow-rocm",
- "tensorflow-macos",
- "tensorflow-aarch64",
- )
- _tf_version = None
- # For the metadata, we have to look for both tensorflow and tensorflow-cpu
- for _pkg in candidates:
- try:
- _tf_version = importlib.metadata.version(_pkg)
- break
- except importlib.metadata.PackageNotFoundError:
- pass
- _tf_available = _tf_version is not None
- if _tf_available:
- if _tf_version and version.parse(_tf_version) < version.parse("2"):
- logger.info(f"TensorFlow found but with version {_tf_version}. OpenLLM only supports TF 2.x")
- _tf_available = False
- else:
- logger.info("Disabling Tensorflow because USE_TORCH is set")
- _tf_available = False
- return _tf_available
-
-
-def is_flax_available():
- global _flax_available
- if USE_JAX in ENV_VARS_TRUE_AND_AUTO_VALUES:
- if _flax_available:
- try:
- importlib.metadata.version("jax")
- importlib.metadata.version("flax")
- except importlib.metadata.PackageNotFoundError:
- _flax_available = False
- else:
- _flax_available = False
- return _flax_available
-
-
-def requires_dependencies(
- package: str | list[str], *, extra: str | list[str] | None = None
-) -> t.Callable[[t.Callable[P, t.Any]], t.Callable[P, t.Any]]:
- import openllm.utils
-
- if isinstance(package, str):
- package = [package]
- if isinstance(extra, str):
- extra = [extra]
-
- def decorator(func: t.Callable[P, t.Any]):
- @functools.wraps(func)
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> t.Any:
- for p in package:
- cached_check: t.Callable[[], bool] | None = getattr(openllm.utils, f"is_{p}_available", None)
- if not ((cached_check is not None and cached_check()) or _is_package_available(p)):
- raise ImportError(
- f"{func.__name__} requires '{p}' to be available locally (Currently missing)."
- f"Make sure to have {p} to be installed: 'pip install \"{p if not extra else 'openllm['+', '.join(extra)+']'}\"'"
- )
- return func(*args, **kwargs)
-
- return wrapper
-
- return decorator
-
-
-PYTORCH_IMPORT_ERROR_WITH_TF = """\
-{0} requires the PyTorch library but it was not found in your environment.
-However, we were able to find a TensorFlow installation. TensorFlow classes begin
-with "TF", but are otherwise identically named to the PyTorch classes. This
-means that the TF equivalent of the class you tried to import would be "TF{0}".
-If you want to use TensorFlow, please use TF classes instead!
-
-If you really do want to use PyTorch please go to
-https://pytorch.org/get-started/locally/ and follow the instructions that
-match your environment.
-"""
-
-TF_IMPORT_ERROR_WITH_PYTORCH = """\
-{0} requires the TensorFlow library but it was not found in your environment.
-However, we were able to find a PyTorch installation. PyTorch classes do not begin
-with "TF", but are otherwise identically named to our TF classes.
-If you want to use PyTorch, please use those classes instead!
-
-If you really do want to use TensorFlow, please follow the instructions on the
-installation page https://www.tensorflow.org/install that match your environment.
-"""
-
-TENSORFLOW_IMPORT_ERROR = """{0} requires the TensorFlow library but it was not found in your environment.
-Checkout the instructions on the installation page: https://www.tensorflow.org/install and follow the
-ones that match your environment. Please note that you may need to restart your runtime after installation.
-"""
-
-
-FLAX_IMPORT_ERROR = """{0} requires the FLAX library but it was not found in your environment.
-Checkout the instructions on the installation page: https://github.com/google/flax and follow the
-ones that match your environment. Please note that you may need to restart your runtime after installation.
-"""
-
-PYTORCH_IMPORT_ERROR = """{0} requires the PyTorch library but it was not found in your environment.
-Checkout the instructions on the installation page: https://pytorch.org/get-started/locally/ and follow the
-ones that match your environment. Please note that you may need to restart your runtime after installation.
-"""
-
-CPM_KERNELS_IMPORT_ERROR = """{0} requires the cpm_kernels library but it was not found in your environment.
-You can install it with pip: `pip install cpm_kernels`. Please note that you may need to restart your
-runtime after installation.
-"""
-
-EINOPS_IMPORT_ERROR = """{0} requires the einops library but it was not found in your environment.
-You can install it with pip: `pip install einops`. Please note that you may need to restart
-your runtime after installation.
-"""
-
-TRITON_IMPORT_ERROR = """{0} requires the triton library but it was not found in your environment.
-You can install it with pip: 'pip install \"git+https://github.com/openai/triton.git#egg=triton&subdirectory=python\"'.
-Please note that you may need to restart your runtime after installation.
-"""
-
-DATASETS_IMPORT_ERROR = """{0} requires the datasets library but it was not found in your environment.
-You can install it with pip: `pip install datasets`. Please note that you may need to restart
-your runtime after installation.
-"""
-
-PEFT_IMPORT_ERROR = """{0} requires the peft library but it was not found in your environment.
-You can install it with pip: `pip install peft`. Please note that you may need to restart
-your runtime after installation.
-"""
-
-BITSANDBYTES_IMPORT_ERROR = """{0} requires the bitsandbytes library but it was not found in your environment.
-You can install it with pip: `pip install bitsandbytes`. Please note that you may need to restart
-your runtime after installation.
-"""
-
-BACKENDS_MAPPING = BackendOrderredDict(
- [
- ("flax", (is_flax_available, FLAX_IMPORT_ERROR)),
- ("tf", (is_tf_available, TENSORFLOW_IMPORT_ERROR)),
- ("torch", (is_torch_available, PYTORCH_IMPORT_ERROR)),
- ("cpm_kernels", (is_cpm_kernels_available, CPM_KERNELS_IMPORT_ERROR)),
- ("einops", (is_einops_available, EINOPS_IMPORT_ERROR)),
- ("triton", (is_triton_available, TRITON_IMPORT_ERROR)),
- ("datasets", (is_datasets_available, DATASETS_IMPORT_ERROR)),
- ("peft", (is_peft_available, PEFT_IMPORT_ERROR)),
- ("bitsandbytes", (is_bitsandbytes_available, BITSANDBYTES_IMPORT_ERROR)),
- ]
-)
-
-
-class DummyMetaclass(ABCMeta):
- """Metaclass for dummy object. It will raises ImportError
- generated by ``require_backends`` if users try to access attributes from given class
- """
-
- _backends: t.List[str]
-
- def __getattribute__(cls, key: str) -> t.Any:
- if key.startswith("_"):
- return super().__getattribute__(key)
- require_backends(cls, cls._backends)
-
-
-def require_backends(o: t.Any, backends: t.MutableSequence[str]):
- if not isinstance(backends, (list, tuple)):
- backends = list(backends)
-
- name = o.__name__ if hasattr(o, "__name__") else o.__class__.__name__
-
- # Raise an error for users who might not realize that classes without "TF" are torch-only
- if "torch" in backends and "tf" not in backends and not is_torch_available() and is_tf_available():
- raise ImportError(PYTORCH_IMPORT_ERROR_WITH_TF.format(name))
-
- # Raise the inverse error for PyTorch users trying to load TF classes
- if "tf" in backends and "torch" not in backends and is_torch_available() and not is_tf_available():
- raise ImportError(TF_IMPORT_ERROR_WITH_PYTORCH.format(name))
-
- checks = (BACKENDS_MAPPING[backend] for backend in backends)
- failed = [msg.format(name) for available, msg in checks if not available()]
- if failed:
- raise ImportError("".join(failed))
-
-
-class EnvVarMixin(ReprMixin):
- model_name: str
-
- @property
- def __repr_keys__(self) -> set[str]:
- return {"config", "model_id", "quantize", "framework", "bettertransformer", "model_version"}
-
- if t.TYPE_CHECKING:
- config: str
- model_id: str
- quantize: str
- framework: str
- bettertransformer: str
- model_version: str
-
- framework_value: t.Literal["pt", "tf", "flax"]
- quantize_value: str | None
- model_version_value: str | None
- bettertransformer_value: str | None
-
- # fmt: off
- @overload
- def __getitem__(self, item: t.Literal["config"]) -> str: ...
- @overload
- def __getitem__(self, item: t.Literal["model_version"]) -> str: ...
- @overload
- def __getitem__(self, item: t.Literal["model_id"]) -> str: ...
- @overload
- def __getitem__(self, item: t.Literal["quantize"]) -> str: ...
- @overload
- def __getitem__(self, item: t.Literal["framework"]) -> str: ...
- @overload
- def __getitem__(self, item: t.Literal["bettertransformer"]) -> str: ...
- @overload
- def __getitem__(self, item: t.Literal['framework_value']) -> t.Literal['pt', 'tf', 'flax']: ...
- @overload
- def __getitem__(self, item: t.Literal['quantize_value']) -> str | None: ...
- @overload
- def __getitem__(self, item: t.Literal['model_version_value']) -> str | None: ...
- @overload
- def __getitem__(self, item: t.Literal['bettertransformer_value']) -> str | None: ...
- # fmt: on
- def __getitem__(self, item: str | t.Any) -> t.Any:
- if hasattr(self, item):
- return getattr(self, item)
- raise KeyError(f"Key {item} not found in {self}")
-
- def __new__(
- cls,
- model_name: str,
- bettertransformer: bool | None = None,
- quantize: t.LiteralString | None = None,
- model_version: str | None = None,
- ):
- from .._configuration import field_env_key
- from . import codegen
-
- model_name = inflection.underscore(model_name)
-
- res = super().__new__(cls)
- res.model_name = model_name
-
- # gen properties env key
- attributes = {"config", "model_id", "quantize", "framework", "bettertransformer", "model_version"}
- for att in attributes:
- setattr(res, att, field_env_key(model_name, att.upper()))
-
- # gen properties env value
- attributes_with_values = {
- "framework": (str, "pt"),
- "quantize": (str, quantize),
- "bettertransformer": (bool, bettertransformer),
- "model_version": (str, model_version),
- }
- globs: dict[str, t.Any] = {
- "__bool_vars_value": ENV_VARS_TRUE_VALUES,
- "__env_get": os.environ.get,
- "self": res,
- }
-
- for attribute, (default_type, default_value) in attributes_with_values.items():
- lines: list[str] = []
- if default_type is bool:
- lines.append(
- f"return str(__env_get(self['{attribute}'], str(__env_default)).upper() in __bool_vars_value)"
- )
- else:
- lines.append(f"return __env_get(self['{attribute}'], __env_default)")
-
- setattr(
- res,
- f"{attribute}_value",
- codegen.generate_function(
- cls,
- "_env_get_" + attribute,
- lines,
- ("__env_default",),
- globs,
- )(default_value),
- )
-
- return res
-
- @property
- def start_docstring(self) -> str:
- return getattr(self.module, f"START_{self.model_name.upper()}_COMMAND_DOCSTRING")
-
- @property
- def module(self) -> LazyLoader:
- return LazyLoader(self.model_name, globals(), f"openllm.models.{self.model_name}")
diff --git a/commune/modules/archive/openllm/src/openllm/utils/lazy.py b/commune/modules/archive/openllm/src/openllm/utils/lazy.py
deleted file mode 100644
index 8082496fa..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/lazy.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import importlib
-import importlib.machinery
-import itertools
-import os
-import types
-import typing as t
-import warnings
-
-from ..exceptions import ForbiddenAttributeError
-from ..exceptions import OpenLLMException
-
-
-class UsageNotAllowedError(OpenLLMException):
- """Raised when LazyModule.__getitem__ is forbidden."""
-
-
-class MissingAttributesError(OpenLLMException):
- """Raised when given keys is not available in LazyModule special mapping."""
-
-
-_sentinel = object()
-
-_reserved_namespace = {"__openllm_special__", "__openllm_migration__"}
-
-
-class LazyModule(types.ModuleType):
- """
- Module class that surfaces all objects but only performs associated imports when the objects are requested.
- This is a direct port from transformers.utils.import_utils._LazyModule for
- backwards compatibility with transformers < 4.18
-
- This is an extension a more powerful LazyLoader.
- """
-
- # Very heavily inspired by optuna.integration._IntegrationModule
- # https://github.com/optuna/optuna/blob/master/optuna/integration/__init__.py
- def __init__(
- self,
- name: str,
- module_file: str,
- import_structure: dict[str, list[str]],
- module_spec: importlib.machinery.ModuleSpec | None = None,
- extra_objects: dict[str, t.Any] | None = None,
- ):
- super().__init__(name)
- self._modules = set(import_structure.keys())
- self._class_to_module: dict[str, str] = {}
- _extra_objects = {} if extra_objects is None else extra_objects
- for key, values in import_structure.items():
- for value in values:
- self._class_to_module[value] = key
- # Needed for autocompletion in an IDE
- self.__all__ = list(import_structure.keys()) + list(itertools.chain(*import_structure.values()))
- self.__file__ = module_file
- self.__spec__ = module_spec
- self.__path__ = [os.path.dirname(module_file)]
- self._objects = _extra_objects
- self._name = name
- self._import_structure = import_structure
-
- # Needed for autocompletion in an IDE
- def __dir__(self):
- result = t.cast("list[str]", super().__dir__())
- # The elements of self.__all__ that are submodules may or
- # may not be in the dir already, depending on whether
- # they have been accessed or not. So we only add the
- # elements of self.__all__ that are not already in the dir.
- for attribute in self.__all__:
- if attribute not in result:
- result.append(attribute)
- return result
-
- def __getitem__(self, key: str) -> t.Any:
- # currently, this is reserved to only internal uses and users shouldn't use this.
- if self._objects.get("__openllm_special__") is None:
- raise UsageNotAllowedError(f"'{self._name}' is not allowed to be used as a dict.")
- _special_mapping = self._objects.get("__openllm_special__", {})
- try:
- if key in _special_mapping:
- return getattr(self, _special_mapping.__getitem__(key))
- raise MissingAttributesError(f"Requested '{key}' is not available in given mapping.")
- except AttributeError as e:
- raise KeyError(f"'{self._name}' has no attribute {_special_mapping[key]}") from e
- except Exception as e:
- raise KeyError(f"Failed to lookup '{key}' in '{self._name}'") from e
-
- def __getattr__(self, name: str) -> t.Any:
- if name in _reserved_namespace:
- raise ForbiddenAttributeError(
- f"'{name}' is a reserved namespace for {self._name} and should not be access nor modified."
- )
- if "__openllm_migration__" in self._objects:
- cur_value = self._objects["__openllm_migration__"].get(name, _sentinel)
- if cur_value is not _sentinel:
- warnings.warn(
- f"'{name}' is deprecated and will be removed in future version. Make sure to use '{cur_value}' instead",
- DeprecationWarning,
- )
- return getattr(self, cur_value)
- if name in self._objects:
- return self._objects.__getitem__(name)
- if name in self._modules:
- value = self._get_module(name)
- elif name in self._class_to_module.keys():
- module = self._get_module(self._class_to_module.__getitem__(name))
- value = getattr(module, name)
- else:
- raise AttributeError(f"module {self.__name__} has no attribute {name}")
-
- setattr(self, name, value)
- return value
-
- def _get_module(self, module_name: str):
- try:
- return importlib.import_module("." + module_name, self.__name__)
- except Exception as e:
- raise RuntimeError(
- f"Failed to import {self.__name__}.{module_name} because of the following error (look up to see its"
- f" traceback):\n{e}"
- ) from e
-
- def __reduce__(self):
- return (self.__class__, (self._name, self.__file__, self._import_structure))
diff --git a/commune/modules/archive/openllm/src/openllm/utils/representation.py b/commune/modules/archive/openllm/src/openllm/utils/representation.py
deleted file mode 100644
index bf267c0a8..000000000
--- a/commune/modules/archive/openllm/src/openllm/utils/representation.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-from abc import abstractmethod
-
-import attr
-import orjson
-
-
-if t.TYPE_CHECKING:
- ReprArgs: t.TypeAlias = t.Iterable[tuple[str | None, t.Any]]
-
-
-class ReprMixin:
- """This class display possible representation of given class.
- It can be used for implementing __rich_pretty__ and __pretty__ methods in the future.
- Most subclass needs to implement a __repr_keys__ property.
-
- Based on the design from Pydantic.
- The __repr__ will display the json representation of the object for easier interaction.
- The __str__ will display either __attrs_repr__ or __repr_str__.
- """
-
- @property
- @abstractmethod
- def __repr_keys__(self) -> set[str]:
- """This can be overriden by base class using this mixin."""
-
- def __repr__(self) -> str:
- from . import bentoml_cattr
-
- serialized = {k: bentoml_cattr.unstructure(v) if attr.has(v) else v for k, v in self.__repr_args__()}
- return f"{self.__class__.__name__} {orjson.dumps(serialized, option=orjson.OPT_INDENT_2).decode()}"
-
- def __str__(self) -> str:
- return self.__repr_str__(" ")
-
- def __repr_name__(self) -> str:
- """Name of the instance's class, used in __repr__."""
- return self.__class__.__name__
-
- def __repr_str__(self, join_str: str) -> str:
- return join_str.join(repr(v) if a is None else f"{a}={repr(v)}" for a, v in self.__repr_args__())
-
- def __repr_args__(self) -> ReprArgs:
- return ((k, getattr(self, k)) for k in self.__repr_keys__)
diff --git a/commune/modules/archive/openllm/src/openllm_client/__init__.py b/commune/modules/archive/openllm/src/openllm_client/__init__.py
deleted file mode 100644
index 5daee98a0..000000000
--- a/commune/modules/archive/openllm/src/openllm_client/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-The actual client implementation. Use ``openllm.client`` instead.
-This holds the implementation of the client, which is used to communicate with the
-OpenLLM server. It is used to send requests to the server, and receive responses.
-"""
-
-from .runtimes.grpc import AsyncGrpcClient as AsyncGrpcClient
-from .runtimes.grpc import GrpcClient as GrpcClient
-from .runtimes.http import AsyncHTTPClient as AsyncHTTPClient
-from .runtimes.http import HTTPClient as HTTPClient
diff --git a/commune/modules/archive/openllm/src/openllm_client/_prompt.py b/commune/modules/archive/openllm/src/openllm_client/_prompt.py
deleted file mode 100644
index 82b694506..000000000
--- a/commune/modules/archive/openllm/src/openllm_client/_prompt.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-from __future__ import annotations
-
-import typing as t
-
-import attr
-
-import openllm
-from openllm._prompt import PromptFormatter
-
-
-if t.TYPE_CHECKING:
- DictStrStr = dict[str, str]
-else:
- DictStrStr = dict
-
-
-# TODO: Support jinja2 template, go template and possible other prompt template engine.
-_default_formatter = PromptFormatter()
-
-
-class PartialDict(DictStrStr):
- def __missing__(self, key: str):
- return "{" + key + "}"
-
-
-@attr.define(slots=True)
-class PromptTemplate:
- template: str
- input_variables: t.Sequence[str]
-
- def to_str(self, __partial_dict__: PartialDict | None = None, **attrs: str) -> str:
- """Generate a prompt from the template and input variables"""
- if __partial_dict__:
- return _default_formatter.vformat(self.template, (), __partial_dict__)
- if not attrs:
- raise ValueError("Keyword arguments are required")
- if not all(k in attrs for k in self.input_variables):
- raise ValueError(f"Missing required input variables: {self.input_variables}")
- return _default_formatter.format(self.template, **attrs)
-
- @classmethod
- def from_template(cls, template: str) -> PromptTemplate:
- input_variables = _default_formatter.extract_template_variables(template)
- return cls(template=template, input_variables=input_variables)
-
- @classmethod
- def from_default(cls, model: str, /, **prompt_attrs: t.Any) -> PromptTemplate:
- template = getattr(openllm.utils.EnvVarMixin(model).module, "DEFAULT_PROMPT_TEMPLATE")
- if template is None:
- raise ValueError(f"Model {model} does not have a default prompt template.")
- if callable(template):
- template = template(**prompt_attrs)
- return cls.from_template(template)
diff --git a/commune/modules/archive/openllm/src/openllm_client/runtimes/__init__.py b/commune/modules/archive/openllm/src/openllm_client/runtimes/__init__.py
deleted file mode 100644
index c4b222142..000000000
--- a/commune/modules/archive/openllm/src/openllm_client/runtimes/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from .grpc import GrpcClient as GrpcClient
-from .http import HTTPClient as HTTPClient
diff --git a/commune/modules/archive/openllm/src/openllm_client/runtimes/base.py b/commune/modules/archive/openllm/src/openllm_client/runtimes/base.py
deleted file mode 100644
index 366e2ca7b..000000000
--- a/commune/modules/archive/openllm/src/openllm_client/runtimes/base.py
+++ /dev/null
@@ -1,327 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import asyncio
-import typing as t
-from abc import abstractmethod
-from urllib.parse import urljoin
-
-import httpx
-
-import bentoml
-import openllm
-import transformers
-
-
-# NOTE: We need to do this so that overload can register
-# correct overloads to typing registry
-if hasattr(t, "get_overloads"):
- from typing import overload
-else:
- from typing_extensions import overload
-
-if t.TYPE_CHECKING:
- from openllm.models.auto.factory import _BaseAutoLLMClass
-
- class AnnotatedClient(bentoml.client.Client):
- def health(self, *args: t.Any, **attrs: t.Any) -> t.Any:
- ...
-
- async def async_health(self) -> t.Any:
- ...
-
- def call(self, name: str, inputs: t.Any, **attrs: t.Any) -> t.Any:
- ...
-
- async def acall(self, name: str, inputs: t.Any, **attrs: t.Any) -> t.Any:
- ...
-
- def generate_v1(self, qa: openllm.GenerationInput) -> dict[str, t.Any]:
- ...
-
- def metadata_v1(self) -> dict[str, t.Any]:
- ...
-
-
-def in_async_context() -> bool:
- try:
- _ = asyncio.get_running_loop()
- return True
- except RuntimeError:
- return False
-
-
-class ClientMixin:
- _api_version: str
- _client_class: type[bentoml.client.Client]
-
- _host: str
- _port: str
-
- __client__: AnnotatedClient | None = None
- __agent__: transformers.HfAgent | None = None
- __llm__: openllm.LLM[t.Any, t.Any] | None = None
-
- def __init__(self, address: str, timeout: int = 30):
- self._address = address
- self._timeout = timeout
- assert self._host and self._port, "Make sure to setup _host and _port based on your client implementation."
-
- def __init_subclass__(cls, *, client_type: t.Literal["http", "grpc"] = "http", api_version: str = "v1"):
- cls._client_class = bentoml.client.HTTPClient if client_type == "http" else bentoml.client.GrpcClient
- cls._api_version = api_version
-
- @property
- def _hf_agent(self) -> transformers.HfAgent:
- if self.__agent__ is None:
- if not openllm.utils.is_transformers_supports_agent():
- raise RuntimeError(
- "Current 'transformers' does not support Agent."
- " Make sure to upgrade to at least 4.29: 'pip install -U \"transformers>=4.29\"'"
- )
- self.__agent__ = transformers.HfAgent(urljoin(self._address, "/hf/agent"))
- return self.__agent__
-
- @property
- def _metadata(self) -> dict[str, t.Any]:
- if in_async_context():
- return httpx.post(urljoin(self._address, f"/{self._api_version}/metadata")).json()
- return self.call("metadata")
-
- @property
- @abstractmethod
- def model_name(self) -> str:
- raise NotImplementedError
-
- @property
- @abstractmethod
- def framework(self) -> t.Literal["pt", "flax", "tf"]:
- raise NotImplementedError
-
- @property
- @abstractmethod
- def timeout(self) -> int:
- raise NotImplementedError
-
- @property
- @abstractmethod
- def model_id(self) -> str:
- raise NotImplementedError
-
- @property
- @abstractmethod
- def configuration(self) -> dict[str, t.Any]:
- raise NotImplementedError
-
- @property
- def llm(self) -> openllm.LLM[t.Any, t.Any]:
- if self.__llm__ is None:
- self.__llm__ = t.cast(
- "_BaseAutoLLMClass",
- openllm[self.framework], # type: ignore (internal API)
- ).for_model(self.model_name)
- return self.__llm__
-
- @property
- def config(self) -> openllm.LLMConfig:
- return self.llm.config
-
- def call(self, name: str, *args: t.Any, **attrs: t.Any) -> t.Any:
- return self._cached.call(f"{name}_{self._api_version}", *args, **attrs)
-
- async def acall(self, name: str, *args: t.Any, **attrs: t.Any) -> t.Any:
- return await self._cached.async_call(f"{name}_{self._api_version}", *args, **attrs)
-
- @property
- def _cached(self) -> AnnotatedClient:
- if self.__client__ is None:
- self._client_class.wait_until_server_ready(self._host, int(self._port), timeout=self._timeout)
- self.__client__ = t.cast("AnnotatedClient", self._client_class.from_url(self._address))
- return self.__client__
-
- def prepare(self, prompt: str, **attrs: t.Any):
- return_raw_response = attrs.pop("return_raw_response", False)
- return return_raw_response, *self.llm.sanitize_parameters(prompt, **attrs)
-
- @abstractmethod
- def postprocess(self, result: t.Any) -> openllm.GenerationOutput:
- ...
-
- @abstractmethod
- def _run_hf_agent(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
- ...
-
-
-class BaseClient(ClientMixin):
- def health(self) -> t.Any:
- raise NotImplementedError
-
- @overload
- def query(self, prompt: str, *, return_raw_response: t.Literal[False] = ..., **attrs: t.Any) -> str:
- ...
-
- @overload
- def query(self, prompt: str, *, return_raw_response: t.Literal[True] = ..., **attrs: t.Any) -> dict[str, t.Any]:
- ...
-
- def query(self, prompt: str, **attrs: t.Any) -> dict[str, t.Any] | str:
- return_raw_response, prompt, generate_kwargs, postprocess_kwargs = self.prepare(prompt, **attrs)
- inputs = openllm.GenerationInput(prompt=prompt, llm_config=self.config.model_construct_env(**generate_kwargs))
- if in_async_context():
- result = httpx.post(
- urljoin(self._address, f"/{self._api_version}/generate"),
- json=openllm.utils.bentoml_cattr.unstructure(inputs),
- timeout=self.timeout,
- ).json()
- else:
- result = self.call("generate", inputs)
- r = self.postprocess(result)
-
- if return_raw_response:
- return openllm.utils.bentoml_cattr.unstructure(r)
-
- return self.llm.postprocess_generate(prompt, r.responses, **postprocess_kwargs)
-
- def ask_agent(
- self,
- task: str,
- *,
- return_code: bool = False,
- remote: bool = False,
- agent_type: t.LiteralString = "hf",
- **attrs: t.Any,
- ) -> t.Any:
- if agent_type == "hf":
- return self._run_hf_agent(task, return_code=return_code, remote=remote, **attrs)
- else:
- raise RuntimeError(f"Unknown 'agent_type={agent_type}'")
-
- def _run_hf_agent(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
- if len(args) > 1:
- raise ValueError("'args' should only take one positional argument.")
- task = kwargs.pop("task", args[0])
- return_code = kwargs.pop("return_code", False)
- remote = kwargs.pop("remote", False)
- return self._hf_agent.run(task, return_code=return_code, remote=remote, **kwargs)
-
- # NOTE: Scikit interface
- def predict(self, prompt: str, **attrs: t.Any) -> t.Any:
- return self.query(prompt, **attrs)
-
- def chat(self, prompt: str, history: list[str], **attrs: t.Any) -> str:
- raise NotImplementedError
-
-
-class BaseAsyncClient(ClientMixin):
- async def health(self) -> t.Any:
- raise NotImplementedError
-
- @overload
- async def query(self, prompt: str, *, return_raw_response: t.Literal[False] = ..., **attrs: t.Any) -> str:
- ...
-
- @overload
- async def query(
- self, prompt: str, *, return_raw_response: t.Literal[True] = ..., **attrs: t.Any
- ) -> dict[str, t.Any]:
- ...
-
- async def query(self, prompt: str, **attrs: t.Any) -> dict[str, t.Any] | str:
- # NOTE: We set use_default_prompt_template to False for now.
- use_default_prompt_template = attrs.pop("use_default_prompt_template", False)
- return_raw_response, prompt, generate_kwargs, postprocess_kwargs = self.prepare(
- prompt, use_default_prompt_template=use_default_prompt_template, **attrs
- )
- inputs = openllm.GenerationInput(prompt=prompt, llm_config=self.config.model_construct_env(**generate_kwargs))
- res = await self.acall("generate", inputs)
- r = self.postprocess(res)
-
- if return_raw_response:
- return openllm.utils.bentoml_cattr.unstructure(r)
-
- return self.llm.postprocess_generate(prompt, r.responses, **postprocess_kwargs)
-
- async def ask_agent(
- self,
- task: str,
- *,
- return_code: bool = False,
- remote: bool = False,
- agent_type: t.LiteralString = "hf",
- **attrs: t.Any,
- ) -> t.Any:
- """Async version of agent.run"""
- if agent_type == "hf":
- return await self._run_hf_agent(task, return_code=return_code, remote=remote, **attrs)
- else:
- raise RuntimeError(f"Unknown 'agent_type={agent_type}'")
-
- async def _run_hf_agent(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
- if len(args) > 1:
- raise ValueError("'args' should only take one positional argument.")
- task = kwargs.pop("task", args[0])
- return_code = kwargs.pop("return_code", False)
- remote = kwargs.pop("remote", False)
-
- from transformers.tools.agents import clean_code_for_run
- from transformers.tools.agents import get_tool_creation_code
- from transformers.tools.agents import resolve_tools
- from transformers.tools.python_interpreter import evaluate
-
- _hf_agent = self._hf_agent
-
- prompt = _hf_agent.format_prompt(task)
- stop = ["Task:"]
- async with httpx.AsyncClient(timeout=httpx.Timeout(self.timeout)) as client:
- response = await client.post(
- _hf_agent.url_endpoint,
- json={
- "inputs": prompt,
- "parameters": {"max_new_tokens": 200, "return_full_text": False, "stop": stop},
- },
- )
- if response.status_code != 200:
- raise ValueError(f"Error {response.status_code}: {response.json()}")
-
- result = response.json()[0]["generated_text"]
- # Inference API returns the stop sequence
- for stop_seq in stop:
- if result.endswith(stop_seq):
- result = result[: -len(stop_seq)]
- break
-
- # the below have the same logic as agent.run API
- explanation, code = clean_code_for_run(result)
-
- _hf_agent.log(f"==Explanation from the agent==\n{explanation}")
-
- _hf_agent.log(f"\n\n==Code generated by the agent==\n{code}")
- if not return_code:
- _hf_agent.log("\n\n==Result==")
- _hf_agent.cached_tools = resolve_tools(
- code, _hf_agent.toolbox, remote=remote, cached_tools=_hf_agent.cached_tools
- )
- return evaluate(code, _hf_agent.cached_tools, state=kwargs.copy())
- else:
- tool_code = get_tool_creation_code(code, _hf_agent.toolbox, remote=remote)
- return f"{tool_code}\n{code}"
-
- # NOTE: Scikit interface
- async def predict(self, prompt: str, **attrs: t.Any) -> t.Any:
- return await self.query(prompt, **attrs)
-
- def chat(self, prompt: str, history: list[str], **attrs: t.Any) -> str:
- raise NotImplementedError
diff --git a/commune/modules/archive/openllm/src/openllm_client/runtimes/grpc.py b/commune/modules/archive/openllm/src/openllm_client/runtimes/grpc.py
deleted file mode 100644
index b32c91c0d..000000000
--- a/commune/modules/archive/openllm/src/openllm_client/runtimes/grpc.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import asyncio
-import logging
-import typing as t
-
-import orjson
-
-import openllm
-
-from .base import BaseAsyncClient
-from .base import BaseClient
-
-
-if t.TYPE_CHECKING:
- import grpc_health.v1.health_pb2 as health_pb2
-
- from bentoml.grpc.v1.service_pb2 import Response
-
-logger = logging.getLogger(__name__)
-
-
-class GrpcClientMixin:
- _metadata: Response
-
- @property
- def model_name(self) -> str:
- try:
- return self._metadata.json.struct_value.fields["model_name"].string_value
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def framework(self) -> t.Literal["pt", "flax", "tf"]:
- try:
- value = self._metadata.json.struct_value.fields["framework"].string_value
- if value not in ("pt", "flax", "tf"):
- raise KeyError
- return value
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def timeout(self) -> int:
- try:
- return int(self._metadata.json.struct_value.fields["timeout"].number_value)
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def model_id(self) -> str:
- try:
- return self._metadata.json.struct_value.fields["model_id"].string_value
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def configuration(self) -> dict[str, t.Any]:
- try:
- v = self._metadata.json.struct_value.fields["configuration"].string_value
- return orjson.loads(v)
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- def postprocess(self, result: Response | dict[str, t.Any]) -> openllm.GenerationOutput:
- if isinstance(result, dict):
- return openllm.GenerationOutput(**result)
-
- from google.protobuf.json_format import MessageToDict
-
- return openllm.GenerationOutput(**MessageToDict(result.json, preserving_proto_field_name=True))
-
-
-class GrpcClient(GrpcClientMixin, BaseClient, client_type="grpc"):
- def __init__(self, address: str, timeout: int = 30):
- self._host, self._port = address.split(":")
- super().__init__(address, timeout)
-
- def health(self) -> health_pb2.HealthCheckResponse:
- return asyncio.run(self._cached.health("bentoml.grpc.v1.BentoService"))
-
-
-class AsyncGrpcClient(GrpcClientMixin, BaseAsyncClient, client_type="grpc"):
- def __init__(self, address: str, timeout: int = 30):
- self._host, self._port = address.split(":")
- super().__init__(address, timeout)
-
- async def health(self) -> health_pb2.HealthCheckResponse:
- return await self._cached.health("bentoml.grpc.v1.BentoService")
diff --git a/commune/modules/archive/openllm/src/openllm_client/runtimes/http.py b/commune/modules/archive/openllm/src/openllm_client/runtimes/http.py
deleted file mode 100644
index 05349379e..000000000
--- a/commune/modules/archive/openllm/src/openllm_client/runtimes/http.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import logging
-import typing as t
-from urllib.parse import urlparse
-
-import orjson
-
-import openllm
-
-from .base import BaseAsyncClient
-from .base import BaseClient
-
-
-logger = logging.getLogger(__name__)
-
-
-class HTTPClientMixin:
- _metadata: dict[str, t.Any]
-
- @property
- def model_name(self) -> str:
- try:
- return self._metadata["model_name"]
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def model_id(self) -> str:
- try:
- return self._metadata["model_name"]
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def framework(self) -> t.Literal["pt", "flax", "tf"]:
- try:
- return self._metadata["framework"]
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def timeout(self) -> int:
- try:
- return self._metadata["timeout"]
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- @property
- def configuration(self) -> dict[str, t.Any]:
- try:
- return orjson.loads(self._metadata["configuration"])
- except KeyError:
- raise RuntimeError("Malformed service endpoint. (Possible malicious)")
-
- def postprocess(self, result: dict[str, t.Any]) -> openllm.GenerationOutput:
- return openllm.GenerationOutput(**result)
-
-
-class HTTPClient(HTTPClientMixin, BaseClient):
- def __init__(self, address: str, timeout: int = 30):
- address = address if "://" in address else "http://" + address
- self._host, self._port = urlparse(address).netloc.split(":")
- super().__init__(address, timeout)
-
- def health(self) -> t.Any:
- return self._cached.health()
-
-
-class AsyncHTTPClient(HTTPClientMixin, BaseAsyncClient):
- def __init__(self, address: str, timeout: int = 30):
- address = address if "://" in address else "http://" + address
- self._host, self._port = urlparse(address).netloc.split(":")
- super().__init__(address, timeout)
-
- async def health(self) -> t.Any:
- return await self._cached.async_health()
diff --git a/commune/modules/archive/openllm/src/openllm_js/package.json b/commune/modules/archive/openllm/src/openllm_js/package.json
deleted file mode 100644
index f1e5e0971..000000000
--- a/commune/modules/archive/openllm/src/openllm_js/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "openllm",
- "version": "0.0.2",
- "description": "TS/JS binding for OpenLLM",
- "type": "module",
- "repository": "git@github.com:bentoml/OpenLLM.git",
- "author": "Aaron Pham <29749331+aarnphm@users.noreply.github.com>",
- "license": "Apache 2.0"
-}
diff --git a/commune/modules/archive/openllm/src/openllm_js/tsconfig.cjs.json b/commune/modules/archive/openllm/src/openllm_js/tsconfig.cjs.json
deleted file mode 100644
index 153eba503..000000000
--- a/commune/modules/archive/openllm/src/openllm_js/tsconfig.cjs.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "module": "nodenext",
- "declaration": false
- },
- "exclude": ["node_modules", "dist", "**/tests"]
-}
diff --git a/commune/modules/archive/openllm/src/openllm_js/tsconfig.json b/commune/modules/archive/openllm/src/openllm_js/tsconfig.json
deleted file mode 100644
index e2c22a35a..000000000
--- a/commune/modules/archive/openllm/src/openllm_js/tsconfig.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "compilerOptions": {
- "outDir": "../../dist",
- "rootDir": "./src",
- "target": "ES2021",
- "module": "ES2020",
- "strict": true,
- "allowJS": true
- },
- "include": ["src/**/*"],
- "exclude": ["node_modules", "dist"]
-}
diff --git a/commune/modules/archive/openllm/taplo.toml b/commune/modules/archive/openllm/taplo.toml
deleted file mode 100644
index 5b930a522..000000000
--- a/commune/modules/archive/openllm/taplo.toml
+++ /dev/null
@@ -1,7 +0,0 @@
-include = ['*.toml']
-
-[formatting]
-align_entries = false
-column_width = 120
-indent_string = " "
-reorder_keys = true
diff --git a/commune/modules/archive/openllm/tests/__init__.py b/commune/modules/archive/openllm/tests/__init__.py
deleted file mode 100644
index 2966d6d1d..000000000
--- a/commune/modules/archive/openllm/tests/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import os
-
-from hypothesis import HealthCheck
-from hypothesis import settings
-
-
-settings.register_profile("CI", settings(suppress_health_check=[HealthCheck.too_slow]), deadline=None)
-
-if "CI" in os.environ:
- settings.load_profile("CI")
diff --git a/commune/modules/archive/openllm/tests/_strategies/__init__.py b/commune/modules/archive/openllm/tests/_strategies/__init__.py
deleted file mode 100644
index 3a2faba50..000000000
--- a/commune/modules/archive/openllm/tests/_strategies/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
diff --git a/commune/modules/archive/openllm/tests/_strategies/_configuration.py b/commune/modules/archive/openllm/tests/_strategies/_configuration.py
deleted file mode 100644
index e088e8aec..000000000
--- a/commune/modules/archive/openllm/tests/_strategies/_configuration.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import logging
-import typing as t
-
-from hypothesis import strategies as st
-
-import openllm
-from openllm._configuration import ModelSettings
-
-
-logger = logging.getLogger(__name__)
-
-env_strats = st.sampled_from([openllm.utils.EnvVarMixin(model_name) for model_name in openllm.CONFIG_MAPPING.keys()])
-
-
-@st.composite
-def model_settings(draw: st.DrawFn):
- """Strategy for generating ModelSettings objects."""
- kwargs: dict[str, t.Any] = {
- "default_id": st.text(min_size=1),
- "model_ids": st.lists(st.text(), min_size=1),
- "url": st.text(),
- "requires_gpu": st.booleans(),
- "trust_remote_code": st.booleans(),
- "requirements": st.none() | st.lists(st.text(), min_size=1),
- "model_type": st.sampled_from(["causal_lm", "seq2seq_lm"]),
- "runtime": st.sampled_from(["transformers", "cpp"]),
- "name_type": st.sampled_from(["dasherize", "lowercase"]),
- "timeout": st.integers(min_value=3600),
- "workers_per_resource": st.one_of(st.integers(min_value=1), st.floats(min_value=0.1, max_value=1.0)),
- }
- return draw(st.builds(ModelSettings, **kwargs))
-
-
-def make_llm_config(
- cls_name: str,
- dunder_config: dict[str, t.Any] | ModelSettings,
- fields: tuple[tuple[t.LiteralString, str, t.Any], ...] | None = None,
- generation_fields: tuple[tuple[t.LiteralString, t.Any], ...] | None = None,
-) -> type[openllm.LLMConfig]:
- globs: dict[str, t.Any] = {"openllm": openllm}
- _config_args: list[str] = []
- lines: list[str] = [f"class {cls_name}Config(openllm.LLMConfig):"]
- for attr, value in dunder_config.items():
- _config_args.append(f'"{attr}": __attr_{attr}')
- globs[f"_{cls_name}Config__attr_{attr}"] = value
- lines.append(f' __config__ = {{ {", ".join(_config_args)} }}')
- if fields is not None:
- for field, type_, default in fields:
- lines.append(f" {field}: {type_} = openllm.LLMConfig.Field({repr(default)})")
- if generation_fields is not None:
- generation_lines = ["class GenerationConfig:"]
- for field, default in generation_fields:
- generation_lines.append(f" {field} = {repr(default)}")
- lines.extend((" " + line for line in generation_lines))
-
- script = "\n".join(lines)
-
- if openllm.utils.DEBUG:
- logger.info("Generated class %s:\n%s", cls_name, script)
-
- eval(compile(script, "name", "exec"), globs)
-
- return globs[f"{cls_name}Config"]
diff --git a/commune/modules/archive/openllm/tests/conftest.py b/commune/modules/archive/openllm/tests/conftest.py
deleted file mode 100644
index 9d723ae78..000000000
--- a/commune/modules/archive/openllm/tests/conftest.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import pytest
-
-
-def pytest_sessionfinish(session: pytest.Session, exitstatus: int):
- # If no tests are collected, pytest exists with code 5, which makes the CI fail.
- if exitstatus == 5:
- session.exitstatus = 0
diff --git a/commune/modules/archive/openllm/tests/models/__init__.py b/commune/modules/archive/openllm/tests/models/__init__.py
deleted file mode 100644
index 3a2faba50..000000000
--- a/commune/modules/archive/openllm/tests/models/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
diff --git a/commune/modules/archive/openllm/tests/models/conftest.py b/commune/modules/archive/openllm/tests/models/conftest.py
deleted file mode 100644
index ac1f40604..000000000
--- a/commune/modules/archive/openllm/tests/models/conftest.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import types
-import typing as t
-
-import pytest
-
-import openllm
-
-
-if t.TYPE_CHECKING:
- from openllm.models.auto.factory import _BaseAutoLLMClass
-
-_FRAMEWORK_MAPPING = {"flan_t5": "google/flan-t5-small", "opt": "facebook/opt-125m"}
-_PROMPT_MAPPING = {
- "qa": "Answer the following yes/no question by reasoning step-by-step. Can you write a whole Haiku in a single tweet?",
- "default": "What is the weather in SF?",
-}
-
-
-def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
- models, fname = t.cast(types.ModuleType, metafunc.module).__name__.partition(".")[-1].split(".")[1:]
-
- if "tf" in fname:
- framework = "tf"
- elif "flax" in fname:
- framework = "flax"
- else:
- framework = "pt"
-
- llm, runner_kwargs = t.cast(
- "_BaseAutoLLMClass",
- openllm[framework], # type: ignore
- ).for_model(models, model_id=_FRAMEWORK_MAPPING[models], return_runner_kwargs=True, ensure_available=True)
- llm.ensure_model_id_exists()
- if "runner" in metafunc.function.__name__:
- llm = llm.to_runner(**runner_kwargs)
- llm.init_local(quiet=True)
-
- if "qa" in metafunc.fixturenames:
- metafunc.parametrize("prompt,llm,qa", [(_PROMPT_MAPPING["qa"], llm, True)])
- else:
- metafunc.parametrize("prompt,llm", [(_PROMPT_MAPPING["default"], llm)])
diff --git a/commune/modules/archive/openllm/tests/models/flan_t5/__init__.py b/commune/modules/archive/openllm/tests/models/flan_t5/__init__.py
deleted file mode 100644
index 3a2faba50..000000000
--- a/commune/modules/archive/openllm/tests/models/flan_t5/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
diff --git a/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_flan_t5.py b/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_flan_t5.py
deleted file mode 100644
index ac277fcdc..000000000
--- a/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_flan_t5.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import openllm
-
-
-def test_small_flan(prompt: str, llm: openllm.LLM[t.Any, t.Any], qa: bool):
- assert llm(prompt)
-
-
-def test_small_runner_flan(prompt: str, llm: openllm.LLMRunner, qa: bool):
- assert llm(prompt)
diff --git a/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_flax_flan_t5.py b/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_flax_flan_t5.py
deleted file mode 100644
index bc8409f8e..000000000
--- a/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_flax_flan_t5.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import openllm
-
-
-@openllm.tests.require_flax
-def test_small_flax_flan(prompt: str, llm: openllm.LLM[t.Any, t.Any], qa: bool):
- assert llm(prompt)
-
-
-@openllm.tests.require_flax
-def test_small_flax_runner_flan(prompt: str, llm: openllm.LLMRunner, qa: bool):
- assert llm(prompt)
diff --git a/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_tf_flan_t5.py b/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_tf_flan_t5.py
deleted file mode 100644
index 0fb2953cb..000000000
--- a/commune/modules/archive/openllm/tests/models/flan_t5/test_modeling_tf_flan_t5.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import openllm
-
-
-@openllm.tests.require_tf
-def test_small_tf_flan(prompt: str, llm: openllm.LLM[t.Any, t.Any], qa: bool):
- assert llm(prompt)
-
-
-@openllm.tests.require_tf
-def test_small_tf_runner_flan(prompt: str, llm: openllm.LLMRunner, qa: bool):
- assert llm(prompt)
diff --git a/commune/modules/archive/openllm/tests/models/opt/__init__.py b/commune/modules/archive/openllm/tests/models/opt/__init__.py
deleted file mode 100644
index 3a2faba50..000000000
--- a/commune/modules/archive/openllm/tests/models/opt/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
diff --git a/commune/modules/archive/openllm/tests/models/opt/test_modeling_flax_opt.py b/commune/modules/archive/openllm/tests/models/opt/test_modeling_flax_opt.py
deleted file mode 100644
index 709993572..000000000
--- a/commune/modules/archive/openllm/tests/models/opt/test_modeling_flax_opt.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import openllm
-
-
-@openllm.tests.require_flax
-def test_small_opt(prompt: str, llm: openllm.LLM[t.Any, t.Any], qa: bool):
- assert llm(prompt)
-
-
-@openllm.tests.require_flax
-def test_small_runner_opt(prompt: str, llm: openllm.LLMRunner, qa: bool):
- assert llm(prompt)
diff --git a/commune/modules/archive/openllm/tests/models/opt/test_modeling_opt.py b/commune/modules/archive/openllm/tests/models/opt/test_modeling_opt.py
deleted file mode 100644
index 1a1d54fa7..000000000
--- a/commune/modules/archive/openllm/tests/models/opt/test_modeling_opt.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import openllm
-
-
-def test_small_opt(prompt: str, llm: openllm.LLM[t.Any, t.Any], qa: bool):
- assert llm(prompt)
-
-
-def test_small_runner_opt(prompt: str, llm: openllm.LLMRunner, qa: bool):
- assert llm(prompt)
diff --git a/commune/modules/archive/openllm/tests/models/opt/test_modeling_tf_opt.py b/commune/modules/archive/openllm/tests/models/opt/test_modeling_tf_opt.py
deleted file mode 100644
index cbbe84bba..000000000
--- a/commune/modules/archive/openllm/tests/models/opt/test_modeling_tf_opt.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import openllm
-
-
-@openllm.tests.require_tf
-def test_small_opt(prompt: str, llm: openllm.LLM[t.Any, t.Any], qa: bool):
- assert llm(prompt)
-
-
-@openllm.tests.require_tf
-def test_small_runner_opt(prompt: str, llm: openllm.LLMRunner, qa: bool):
- assert llm(prompt)
diff --git a/commune/modules/archive/openllm/tests/test_client.py b/commune/modules/archive/openllm/tests/test_client.py
deleted file mode 100644
index 59c485586..000000000
--- a/commune/modules/archive/openllm/tests/test_client.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import openllm
-
-
-def test_import_client():
- assert len(openllm.client.__all__) == 4
- assert all(
- hasattr(openllm.client, attr) for attr in ("AsyncGrpcClient", "GrpcClient", "AsyncHTTPClient", "HTTPClient")
- )
diff --git a/commune/modules/archive/openllm/tests/test_configuration.py b/commune/modules/archive/openllm/tests/test_configuration.py
deleted file mode 100644
index a03023714..000000000
--- a/commune/modules/archive/openllm/tests/test_configuration.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""All configuration-related tests for openllm.LLMConfig. This will include testing
-for ModelEnv construction and parsing environment variables."""
-from __future__ import annotations
-
-import contextlib
-import logging
-import os
-import typing as t
-from unittest import mock
-
-import attr
-import pytest
-from hypothesis import assume
-from hypothesis import given
-from hypothesis import strategies as st
-
-import openllm
-import transformers
-from openllm._configuration import GenerationConfig
-from openllm._configuration import ModelSettings
-from openllm._configuration import field_env_key
-
-from ._strategies._configuration import make_llm_config
-from ._strategies._configuration import model_settings
-
-
-logger = logging.getLogger(__name__)
-
-if t.TYPE_CHECKING:
- DictStrAny = dict[str, t.Any]
-else:
- DictStrAny = dict
-
-
-def test_missing_default():
- with pytest.raises(ValueError, match="Either 'default_id' or 'model_ids'*"):
- make_llm_config("MissingDefaultId", {"name_type": "lowercase", "requirements": ["bentoml"]})
-
- with pytest.raises(ValueError, match="Either 'default_id' or 'model_ids'*"):
- make_llm_config("MissingModelId", {"default_id": "huggingface/t5-tiny-testing", "requirements": ["bentoml"]})
-
-
-def test_forbidden_access():
- cl_ = make_llm_config(
- "ForbiddenAccess",
- {
- "default_id": "huggingface/t5-tiny-testing",
- "model_ids": ["huggingface/t5-tiny-testing", "bentoml/t5-tiny-testing"],
- "requirements": ["bentoml"],
- },
- )
-
- assert pytest.raises(
- openllm.exceptions.ForbiddenAttributeError,
- cl_.__getattribute__,
- cl_(),
- "__config__",
- )
- assert pytest.raises(
- openllm.exceptions.ForbiddenAttributeError,
- cl_.__getattribute__,
- cl_(),
- "GenerationConfig",
- )
-
- assert openllm.utils.lenient_issubclass(cl_.__openllm_generation_class__, GenerationConfig)
-
-
-@given(model_settings())
-def test_class_normal_gen(gen_settings: ModelSettings):
- assume(gen_settings["default_id"] and all(i for i in gen_settings["model_ids"]))
- cl_: type[openllm.LLMConfig] = make_llm_config("NotFullLLM", gen_settings)
- assert issubclass(cl_, openllm.LLMConfig)
- for key in gen_settings:
- assert object.__getattribute__(cl_, f"__openllm_{key}__") == gen_settings.__getitem__(key)
-
-
-@given(model_settings(), st.integers())
-def test_simple_struct_dump(gen_settings: ModelSettings, field1: int):
- cl_ = make_llm_config("IdempotentLLM", gen_settings, fields=(("field1", "float", field1),))
- assert cl_().model_dump()["field1"] == field1
-
-
-@given(model_settings(), st.integers())
-def test_config_derivation(gen_settings: ModelSettings, field1: int):
- cl_ = make_llm_config("IdempotentLLM", gen_settings, fields=(("field1", "float", field1),))
- new_cls = cl_.model_derivate("DerivedLLM", default_id="asdfasdf")
- assert new_cls.__openllm_default_id__ == "asdfasdf"
-
-
-@given(model_settings())
-def test_config_derived_follow_attrs_protocol(gen_settings: ModelSettings):
- cl_ = make_llm_config("AttrsProtocolLLM", gen_settings)
- assert attr.has(cl_)
-
-
-@given(
- model_settings(),
- st.integers(max_value=283473),
- st.floats(min_value=0.0, max_value=1.0),
- st.integers(max_value=283473),
- st.floats(min_value=0.0, max_value=1.0),
-)
-def test_complex_struct_dump(
- gen_settings: ModelSettings, field1: int, temperature: float, input_field1: int, input_temperature: float
-):
- cl_ = make_llm_config(
- "ComplexLLM",
- gen_settings,
- fields=(("field1", "float", field1),),
- generation_fields=(("temperature", temperature),),
- )
- sent = cl_()
- assert (
- sent.model_dump()["field1"] == field1 and sent.model_dump()["generation_config"]["temperature"] == temperature
- )
- assert (
- sent.model_dump(flatten=True)["field1"] == field1
- and sent.model_dump(flatten=True)["temperature"] == temperature
- )
-
- passed = cl_(field1=input_field1, temperature=input_temperature)
- assert (
- passed.model_dump()["field1"] == input_field1
- and passed.model_dump()["generation_config"]["temperature"] == input_temperature
- )
- assert (
- passed.model_dump(flatten=True)["field1"] == input_field1
- and passed.model_dump(flatten=True)["temperature"] == input_temperature
- )
-
- pas_nested = cl_(generation_config={"temperature": input_temperature}, field1=input_field1)
- assert (
- pas_nested.model_dump()["field1"] == input_field1
- and pas_nested.model_dump()["generation_config"]["temperature"] == input_temperature
- )
-
-
-@contextlib.contextmanager
-def patch_env(**attrs: t.Any):
- with mock.patch.dict(os.environ, attrs, clear=True):
- yield
-
-
-def test_struct_envvar():
- with patch_env(
- **{
- field_env_key("env_llm", "field1"): "4",
- field_env_key("env_llm", "temperature", suffix="generation"): "0.2",
- }
- ):
-
- class EnvLLM(openllm.LLMConfig):
- __config__ = {"default_id": "asdfasdf", "model_ids": ["asdf", "asdfasdfads"]}
- field1: int = 2
-
- class GenerationConfig:
- temperature: float = 0.8
-
- sent = EnvLLM.model_construct_env()
- assert sent.field1 == 4
- assert sent["temperature"] == 0.2
-
- overwrite_default = EnvLLM()
- assert overwrite_default.field1 == 4
- assert overwrite_default["temperature"] == 0.2
-
-
-def test_struct_provided_fields():
- class EnvLLM(openllm.LLMConfig):
- __config__ = {"default_id": "asdfasdf", "model_ids": ["asdf", "asdfasdfads"]}
- field1: int = 2
-
- class GenerationConfig:
- temperature: float = 0.8
-
- sent = EnvLLM.model_construct_env(field1=20, temperature=0.4)
- assert sent.field1 == 20
- assert sent.generation_config.temperature == 0.4
-
-
-def test_struct_envvar_with_overwrite_provided_env(monkeypatch: pytest.MonkeyPatch):
- with monkeypatch.context() as mk:
- mk.setenv(field_env_key("overwrite_with_env_available", "field1"), str(4.0))
- mk.setenv(field_env_key("overwrite_with_env_available", "temperature", suffix="generation"), str(0.2))
- sent = make_llm_config(
- "OverwriteWithEnvAvailable",
- {"default_id": "asdfasdf", "model_ids": ["asdf", "asdfasdfads"]},
- fields=(("field1", "float", 3.0),),
- ).model_construct_env(field1=20.0, temperature=0.4)
- assert sent.generation_config.temperature == 0.4
- assert sent.field1 == 20.0
-
-
-@given(model_settings())
-@pytest.mark.parametrize("return_dict,typ", [(True, DictStrAny), (False, transformers.GenerationConfig)])
-def test_conversion_to_transformers(return_dict: bool, typ: type[t.Any], gen_settings: ModelSettings):
- cl_ = make_llm_config("ConversionLLM", gen_settings)
- assert isinstance(cl_().to_generation_config(return_as_dict=return_dict), typ)
-
-
-@given(model_settings())
-def test_click_conversion(gen_settings: ModelSettings):
- # currently our conversion omit Union type.
- def cli_mock(**attrs: t.Any):
- return attrs
-
- cl_ = make_llm_config("ClickConversionLLM", gen_settings)
- wrapped = cl_.to_click_options(cli_mock)
- filtered = {k for k, v in cl_.__openllm_hints__.items() if t.get_origin(v) is not t.Union}
- click_options_filtered = [i for i in wrapped.__click_params__ if i.name and not i.name.startswith("fake_")]
- assert len(filtered) == len(click_options_filtered)
-
-
-@pytest.mark.parametrize("model_name", openllm.CONFIG_MAPPING.keys())
-def test_configuration_dict_protocol(model_name: str):
- config = openllm.AutoConfig.for_model(model_name)
- assert isinstance(config.items(), list)
- assert isinstance(config.keys(), list)
- assert isinstance(config.values(), list)
- assert isinstance(dict(config), dict)
diff --git a/commune/modules/archive/openllm/tests/test_package.py b/commune/modules/archive/openllm/tests/test_package.py
deleted file mode 100644
index 8c8826999..000000000
--- a/commune/modules/archive/openllm/tests/test_package.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import pytest
-
-import openllm
-from bentoml._internal.configuration.containers import BentoMLContainer
-
-
-if t.TYPE_CHECKING:
- from pathlib import Path
-
-
-HF_INTERNAL_T5_TESTING = "hf-internal-testing/tiny-random-t5"
-
-
-def test_general_build_with_internal_testing():
- bento_store = BentoMLContainer.bento_store.get()
-
- llm = openllm.AutoLLM.for_model("flan-t5", model_id=HF_INTERNAL_T5_TESTING)
- bento = openllm.build("flan-t5", model_id=HF_INTERNAL_T5_TESTING)
-
- assert llm.llm_type == bento.info.labels["_type"]
- assert llm.config["env"]["framework_value"] == bento.info.labels["_framework"]
-
- bento = openllm.build("flan-t5", model_id=HF_INTERNAL_T5_TESTING)
- assert len(bento_store.list(bento.tag)) == 1
-
-
-def test_general_build_from_local(tmp_path_factory: pytest.TempPathFactory):
- bento_store = BentoMLContainer.bento_store.get()
-
- local_path = tmp_path_factory.mktemp("local_t5")
- llm = openllm.AutoLLM.for_model("flan-t5", model_id=HF_INTERNAL_T5_TESTING, ensure_available=True)
-
- if llm.bettertransformer:
- llm.__llm_model__ = llm.model.reverse_bettertransformer()
-
- llm.model.save_pretrained(local_path.__fspath__())
- llm.tokenizer.save_pretrained(local_path.__fspath__())
-
- bento = openllm.build("flan-t5", model_id=local_path.resolve().__fspath__(), model_version="1")
- assert len(bento_store.list(bento.tag)) == 1
-
- bento = openllm.build("flan-t5", model_id=local_path.resolve().__fspath__(), model_version="1")
- assert len(bento_store.list(bento.tag)) == 1
-
-
-@pytest.fixture(name="dockerfile_template", scope="function")
-def fixture_dockerfile_template(tmp_path_factory: pytest.TempPathFactory):
- file = tmp_path_factory.mktemp("dockerfiles") / "Dockerfile.template"
- file.write_text(
- "\n".join(
- [
- "{% extends bento_base_template %}",
- "{% block SETUP_BENTO_ENTRYPOINT %}",
- "{{ super() }}",
- "RUN echo 'sanity from custom dockerfile'",
- "{% endblock %}",
- ]
- )
- )
- return file
-
-
-@pytest.mark.usefixtures("dockerfile_template")
-def test_build_with_custom_dockerfile(dockerfile_template: Path):
- assert openllm.build(
- "flan-t5",
- model_id=HF_INTERNAL_T5_TESTING,
- overwrite_existing_bento=True,
- dockerfile_template=str(dockerfile_template),
- )
diff --git a/commune/modules/archive/openllm/tests/test_strategies.py b/commune/modules/archive/openllm/tests/test_strategies.py
deleted file mode 100644
index 652013081..000000000
--- a/commune/modules/archive/openllm/tests/test_strategies.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import typing as t
-
-import pytest
-
-
-if t.TYPE_CHECKING:
- from _pytest.monkeypatch import MonkeyPatch
-
-import bentoml
-from bentoml._internal.resource import get_resource
-from openllm import _strategies as strategy
-from openllm._strategies import CascadingResourceStrategy
-
-
-class GPURunnable(bentoml.Runnable):
- SUPPORTED_RESOURCES = ("nvidia.com/gpu", "amd.com/gpu")
-
-
-def unvalidated_get_resource(x: dict[str, t.Any], y: str):
- return get_resource(x, y, validate=False)
-
-
-@pytest.mark.parametrize("gpu_type", ["nvidia.com/gpu", "amd.com/gpu"])
-def test_cascade_strategy_worker_count(monkeypatch: MonkeyPatch, gpu_type: str):
- monkeypatch.setattr(strategy, "get_resource", unvalidated_get_resource)
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: 2}, 1) == 2
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: 2}, 2) == 4
- assert pytest.raises(
- ValueError,
- CascadingResourceStrategy.get_worker_count,
- GPURunnable,
- {gpu_type: 0},
- 1,
- )
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: [2, 7]}, 1) == 2
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: [2, 7]}, 2) == 4
-
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: [2, 7]}, 0.5) == 1
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: [2, 7, 9]}, 0.5) == 2
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: [2, 7, 8, 9]}, 0.5) == 2
- assert CascadingResourceStrategy.get_worker_count(GPURunnable, {gpu_type: [2, 5, 7, 8, 9]}, 0.4) == 2
-
-
-@pytest.mark.parametrize("gpu_type", ["nvidia.com/gpu", "amd.com/gpu"])
-def test_cascade_strategy_worker_env(monkeypatch: MonkeyPatch, gpu_type: str):
- monkeypatch.setattr(strategy, "get_resource", unvalidated_get_resource)
-
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 1, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "0"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 1, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "1"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7]}, 1, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "7"
-
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 2, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "0"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 2, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "0"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 2, 2)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "1"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7]}, 2, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "2"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7]}, 2, 2)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "7"
-
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7]}, 0.5, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "2,7"
-
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7, 8, 9]}, 0.5, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "2,7"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7, 8, 9]}, 0.5, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "8,9"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 7, 8, 9]}, 0.25, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "2,7,8,9"
-
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 6, 7, 8, 9]}, 0.4, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "2,6"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 6, 7, 8, 9]}, 0.4, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "7,8"
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: [2, 6, 7, 8, 9]}, 0.4, 2)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "9"
-
-
-@pytest.mark.parametrize("gpu_type", ["nvidia.com/gpu", "amd.com/gpu"])
-def test_cascade_strategy_disabled_via_env(monkeypatch: MonkeyPatch, gpu_type: str):
- monkeypatch.setattr(strategy, "get_resource", unvalidated_get_resource)
-
- monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "")
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 1, 0)
- assert envs.get("CUDA_VISIBLE_DEVICES") == ""
- monkeypatch.delenv("CUDA_VISIBLE_DEVICES")
-
- monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "-1")
- envs = CascadingResourceStrategy.get_worker_env(GPURunnable, {gpu_type: 2}, 1, 1)
- assert envs.get("CUDA_VISIBLE_DEVICES") == "-1"
- monkeypatch.delenv("CUDA_VISIBLE_DEVICES")
diff --git a/commune/modules/archive/openllm/tools/add-license-headers b/commune/modules/archive/openllm/tools/add-license-headers
deleted file mode 100755
index de6361b59..000000000
--- a/commune/modules/archive/openllm/tools/add-license-headers
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-if ! command -v addlicense @ >&1 > /dev/null; then
- if command -v go @ >&1 > /dev/null; then
- go install github.com/google/addlicense@latest
- else
- echo "ERROR: addlicense not installed."
- echo "Install using https://github.com/google/addlicense#install"
- echo "Tip: If you have go installed, run 'go install github.com/google/addlicense@latest'"
- exit 1
- fi
-fi
-
-addlicense -v -l apache -c 'BentoML Team. All rights reserved.' \
- -ignore .github/workflows/binary-releases.yml \
- -ignore src/openllm/playground/features.py \
- -ignore src/openllm/playground/opt_tuned.py \
- -ignore src/openllm/playground/falcon_tuned.py \
- "$@"
diff --git a/commune/modules/archive/openllm/tools/assert-license-headers b/commune/modules/archive/openllm/tools/assert-license-headers
deleted file mode 100755
index 6c9aa1321..000000000
--- a/commune/modules/archive/openllm/tools/assert-license-headers
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-# License header pattern
-LICENSE_HEADER=$(
- cat << 'EOF'
-# Copyright [0-9]{4} BentoML Team. All rights reserved.
-EOF
-)
-
-# Path to the file being checked
-FILE="$1"
-
-# Check if the license header is present in the file
-if ! grep -Eq "$LICENSE_HEADER" "$FILE"; then
- echo "Make sure to run ./tools/add-license-headers ."
- exit 1
-fi
-
-exit 0
diff --git a/commune/modules/archive/openllm/tools/assert-model-table-latest b/commune/modules/archive/openllm/tools/assert-model-table-latest
deleted file mode 100755
index 0bd784142..000000000
--- a/commune/modules/archive/openllm/tools/assert-model-table-latest
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-
-from __future__ import annotations
-
-import os
-import subprocess
-import sys
-
-from markdown_it import MarkdownIt
-
-
-md = MarkdownIt()
-
-ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-with open(os.path.join(ROOT, "README.md"), "r") as f:
- readme = md.parse(f.read())
-
-# NOTE: Currently, we only have one table in README, which is the Model readme.
-table = [r for r in readme if r.type == "html_block" and r.content.startswith(" int:
- coverage_report = ROOT / "coverage.xml"
- root = etree.fromstring(coverage_report.read_text())
-
- raw_package_data: defaultdict[str, dict[str, int]] = defaultdict(lambda: {"hits": 0, "misses": 0})
- for package in root.find("packages"):
- for module in package.find("classes"):
- filename = module.attrib["filename"]
- for relative_path, package_name in PACKAGES.items():
- if filename.startswith(relative_path):
- data = raw_package_data[package_name]
- break
- else:
- message = f"unknown package: {module}"
- raise ValueError(message)
-
- for line in module.find("lines"):
- if line.attrib["hits"] == "1":
- data["hits"] += 1
- else:
- data["misses"] += 1
-
- total_statements_covered = 0
- total_statements = 0
- coverage_data = {}
- for package_name, data in sorted(raw_package_data.items()):
- statements_covered = data["hits"]
- statements = statements_covered + data["misses"]
- total_statements_covered += statements_covered
- total_statements += statements
-
- coverage_data[package_name] = {"statements_covered": statements_covered, "statements": statements}
- coverage_data["total"] = {"statements_covered": total_statements_covered, "statements": total_statements}
-
- coverage_summary = ROOT / "coverage-summary.json"
- coverage_summary.write_text(orjson.dumps(coverage_data, option=orjson.OPT_INDENT_2).decode(), encoding="utf-8")
-
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/commune/modules/archive/openllm/tools/run-release-action b/commune/modules/archive/openllm/tools/run-release-action
deleted file mode 100755
index b454becdf..000000000
--- a/commune/modules/archive/openllm/tools/run-release-action
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env bash
-
-set -e -o pipefail
-
-# Function to print script usage
-print_usage() {
- echo "Usage: $0 [--release ]"
-}
-
-# Function to validate release argument
-validate_release() {
- local release=$1
-
- if [[ $release == "major" || $release == "minor" || $release == "patch" ]]; then
- return 0
- else
- return 1
- fi
-}
-
-if ! command -v gh @ >&1 > /dev/null; then
- echo "ERROR: gh not installed. Aborting..."
- exit 1
-fi
-
-if ! command -v jq @ >&1 > /dev/null; then
- echo "ERROR: jq not installed. Aborting..."
- exit 1
-fi
-
-if ! command -v hatch @ >&1 > /dev/null; then
- echo "ERROR: hatch not installed. Aborting..."
- exit 1
-fi
-
-# Check if release flag is provided
-if [[ $1 == "--release" ]]; then
- # Check if release argument is provided
- if [[ -z $2 ]]; then
- echo "Error: No release argument provided."
- print_usage
- exit 1
- fi
-
- release=$2
-
- if ! validate_release "$release"; then
- echo "Error: Invalid release argument. Only 'major', 'minor', or 'patch' are allowed."
- print_usage
- exit 1
- fi
-else
- echo "Error: Unknown option or no option provided."
- print_usage
- exit 1
-fi
-
-echo "Running release actions (create-releases.yml)..."
-echo '{"release_type": "'"$release"'"}' | gh workflow run create-releases.yml --repo bentoml/openllm --json
-
-sleep 10
-
-echo "Getting 'create-releases.yml' workflow id..."
-WORKFLOW_ID=$(gh run list -w release --repo bentoml/openllm -L 1 --json databaseId | jq '.[]| .databaseId')
-
-echo "Waiting for workflow create-releases.yml to complete..."
-while true; do
- STATUS=$(gh run view "$WORKFLOW_ID" --json status --jq '.status')
- if [[ "${STATUS}" == "completed" ]]; then
- break
- fi
- sleep 10
-done
-
-sleep 10
diff --git a/commune/modules/archive/openllm/tools/update-config-stubs.py b/commune/modules/archive/openllm/tools/update-config-stubs.py
deleted file mode 100755
index fc74c0ed4..000000000
--- a/commune/modules/archive/openllm/tools/update-config-stubs.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-import importlib
-import os
-from pathlib import Path
-
-import openllm
-from openllm._configuration import GenerationConfig
-from openllm._configuration import ModelSettings
-from openllm._configuration import PeftType
-
-
-# currently we are assuming the indentatio level is 4 for comments
-START_COMMENT = f"# {os.path.basename(__file__)}: start\n"
-END_COMMENT = f"# {os.path.basename(__file__)}: stop\n"
-
-_TARGET_FILE = Path(__file__).parent.parent / "src" / "openllm" / "_configuration.py"
-
-_imported = importlib.import_module(ModelSettings.__module__)
-
-
-def process_annotations(annotations: str) -> str:
- if "NotRequired" in annotations:
- return annotations[len("NotRequired[") : -1]
- elif "Required" in annotations:
- return annotations[len("Required[") : -1]
- else:
- return annotations
-
-
-def main() -> int:
- transformed = {"fine_tune_strategies": "t.Dict[AdapterType, FineTuneConfig]"}
- with _TARGET_FILE.open("r") as f:
- processed = f.readlines()
-
- start_idx, end_idx = processed.index(" " * 4 + START_COMMENT), processed.index(" " * 4 + END_COMMENT)
-
- lines: list[str]= []
- for keys, ForwardRef in openllm.utils.codegen.get_annotations(ModelSettings).items():
- lines.extend(
- [
- " " * 4 + line
- for line in [
- "@overload\n" if "overload" in dir(_imported) else "@t.overload\n",
- f'def __getitem__(self, item: t.Literal["{keys}"] = ...) -> {transformed.get(keys, process_annotations(ForwardRef.__forward_arg__))}: ...\n',
- ]
- ]
- )
- # special case variables: generation_class, extras
- lines.extend(
- [
- " " * 4 + line
- for line in [
- "@overload\n" if "overload" in dir(_imported) else "@t.overload\n",
- 'def __getitem__(self, item: t.Literal["generation_class"] = ...) -> t.Type[GenerationConfig]: ...\n',
- "@overload\n" if "overload" in dir(_imported) else "@t.overload\n",
- 'def __getitem__(self, item: t.Literal["extras"] = ...) -> t.Dict[str, t.Any]: ...\n',
- ]
- ]
- )
- for keys, type_pep563 in openllm.utils.codegen.get_annotations(GenerationConfig).items():
- lines.extend(
- [
- " " * 4 + line
- for line in [
- "@overload\n" if "overload" in dir(_imported) else "@t.overload\n",
- f'def __getitem__(self, item: t.Literal["{keys}"] = ...) -> {type_pep563}: ...\n',
- ]
- ]
- )
-
- for keys in PeftType._member_names_:
- lines.extend(
- [
- " " * 4 + line
- for line in [
- "@overload\n" if "overload" in dir(_imported) else "@t.overload\n",
- f'def __getitem__(self, item: t.Literal["{keys.lower()}"] = ...) -> dict[str, t.Any]: ...\n',
- ]
- ]
- )
-
- processed = (
- processed[:start_idx] + [" " * 4 + START_COMMENT] + lines + [" " * 4 + END_COMMENT] + processed[end_idx + 1 :]
- )
- with _TARGET_FILE.open("w") as f:
- f.writelines(processed)
-
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/commune/modules/archive/openllm/tools/update-optional-dependencies.py b/commune/modules/archive/openllm/tools/update-optional-dependencies.py
deleted file mode 100755
index 2facab2ed..000000000
--- a/commune/modules/archive/openllm/tools/update-optional-dependencies.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-from __future__ import annotations
-
-import dataclasses
-import os
-import shutil
-import typing as t
-
-import inflection
-import tomlkit
-
-import openllm
-
-
-ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-@dataclasses.dataclass(frozen=True)
-class Dependencies:
- name: str
- git_repo_url: t.Optional[str] = None
- branch: t.Optional[str] = None
- extensions: t.Optional[t.List[str]] = None
- subdirectory: t.Optional[str] = None
- requires_gpu: bool = False
- lower_constraint: t.Optional[str] = None
-
- def with_options(self, **kwargs: t.Any) -> Dependencies:
- return dataclasses.replace(self, **kwargs)
-
- @property
- def has_constraint(self) -> bool:
- return self.lower_constraint is not None
-
- @property
- def pypi_extensions(self) -> str:
- return "" if self.extensions is None else f"[{','.join(self.extensions)}]"
-
- def to_str(self) -> str:
- if self.lower_constraint is not None:
- return f"{self.name}{self.pypi_extensions}>={self.lower_constraint}"
- elif self.subdirectory is not None:
- return f"{self.name}{self.pypi_extensions} @ git+https://github.com/{self.git_repo_url}.git#subdirectory={self.subdirectory}"
- elif self.branch is not None:
- return f"{self.name}{self.pypi_extensions} @ git+https://github.com/{self.git_repo_url}.git@{self.branch}"
- else:
- return f"{self.name}{self.pypi_extensions}"
-
- @classmethod
- def from_tuple(cls, *decls: t.Any) -> Dependencies:
- return cls(*decls)
-
-
-_BENTOML_EXT = ["grpc", "io"]
-_TRANSFORMERS_EXT = ["torch", "tokenizers", "accelerate"]
-
-_BASE_DEPENDENCIES = [
- Dependencies(name="bentoml", extensions=_BENTOML_EXT, lower_constraint="1.0.22"),
- Dependencies(name="transformers", extensions=_TRANSFORMERS_EXT, lower_constraint="4.29.0"),
- Dependencies(name="optimum"),
- Dependencies(name="attrs", lower_constraint="23.1.0"),
- Dependencies(name="cattrs", lower_constraint="23.1.0"),
- Dependencies(name="orjson"),
- Dependencies(name="inflection"),
- Dependencies(name="tabulate", extensions=["widechars"], lower_constraint="0.9.0"),
- Dependencies(name="httpx"),
- Dependencies(name="typing_extensions"),
-]
-
-_NIGHTLY_MAPPING: dict[str, Dependencies] = {
- "bentoml": Dependencies.from_tuple("bentoml", "bentoml/bentoml", "main", _BENTOML_EXT),
- "peft": Dependencies.from_tuple("peft", "huggingface/peft", "main", None),
- "transformers": Dependencies.from_tuple("transformers", "huggingface/transformers", "main", _TRANSFORMERS_EXT),
- "optimum": Dependencies.from_tuple("optimum", "huggingface/optimum", "main", None),
- "accelerate": Dependencies.from_tuple("accelerate", "huggingface/accelerate", "main", None),
- "bitsandbytes": Dependencies.from_tuple("bitsandbytes", "TimDettmers/bitsandbytes", "main", None),
- "deepspeed": Dependencies.from_tuple("deepspeed", "microsoft/deepspeed", "master", None),
- "trl": Dependencies.from_tuple("trl", "lvwerra/trl", "main", None),
- "triton": Dependencies.from_tuple("triton", "openai/triton", "main", None, "python", True),
-}
-
-FINE_TUNE_DEPS = ["peft", "bitsandbytes", "datasets", "accelerate", "deepspeed", "trl"]
-FLAN_T5_DEPS = ["flax", "jax", "jaxlib", "tensorflow", "keras"]
-MPT_DEPS = ["triton"]
-OPENAI_DEPS = ["openai", "tiktoken"]
-AGENTS_DEPS = ["transformers[agents]>=4.30", "diffusers", "soundfile"]
-FALCON_DEPS = ["einops", "xformers", "safetensors"]
-STARCODER_DEPS = ["bitsandbytes"]
-CHATGLM_DEPS = ["cpm-kernels", "sentencepiece"]
-PLAYGROUND_DEPS = ["jupyter", "notebook", "ipython", "jupytext", "nbformat"]
-
-_base_requirements = {
- inflection.dasherize(name): config_cls.__openllm_requirements__
- for name, config_cls in openllm.CONFIG_MAPPING.items()
- if config_cls.__openllm_requirements__
-}
-
-# shallow copy from locals()
-_locals = locals().copy()
-
-# NOTE: update this table when adding new external dependencies
-# sync with openllm.utils.OPTIONAL_DEPENDENCIES
-_base_requirements.update(
- {v: _locals[f"{inflection.underscore(v).upper()}_DEPS"] for v in openllm.utils.OPTIONAL_DEPENDENCIES}
-)
-
-
-def main() -> int:
- with open(os.path.join(ROOT, "pyproject.toml"), "r") as f:
- pyproject = tomlkit.parse(f.read())
-
- table = tomlkit.table()
- for name, config in _base_requirements.items():
- table.add(name, config)
-
- table.add("all", [f"openllm[{k}]" for k in table.keys()])
-
- pyproject["project"]["optional-dependencies"] = table
-
- # write project dependencies
- pyproject["project"]["dependencies"] = [v.to_str() for v in _BASE_DEPENDENCIES]
- with open(os.path.join(ROOT, "pyproject.toml"), "w") as f:
- f.write(tomlkit.dumps(pyproject))
-
- with open(os.path.join(ROOT, "nightly-requirements.txt"), "w") as f:
- f.write("# This file is generated by `./tools/update-optional-dependencies.py`\n# DO NOT EDIT\n-e .[all]\n")
- f.writelines([f"{v.to_str()}\n" for v in _NIGHTLY_MAPPING.values() if not v.requires_gpu])
- with open(os.path.join(ROOT, "nightly-requirements-gpu.txt"), "w") as f:
- f.write("# This file is generated by `./tools/update-optional-dependencies.py`\n# DO NOT EDIT\n")
- f.write(
- "# For Jax, Flax, Tensorflow, PyTorch CUDA support, please refers to their official installation for your specific setup.\n"
- )
- f.write("-r nightly-requirements.txt\n")
- f.writelines([f"{v.to_str()}\n" for v in _NIGHTLY_MAPPING.values() if v.requires_gpu])
-
- os.system("git update-index -q --refresh")
- if os.system("git diff-index --quiet HEAD -- nightly-requirements.txt") == 0 and shutil.which("taplo"):
- return os.system(f"taplo fmt {os.path.join(ROOT, 'pyproject.toml')}")
-
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/commune/modules/archive/openllm/tools/update-readme.py b/commune/modules/archive/openllm/tools/update-readme.py
deleted file mode 100755
index 2f490912c..000000000
--- a/commune/modules/archive/openllm/tools/update-readme.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-from __future__ import annotations
-
-import os
-import typing as t
-
-import inflection
-import tomlkit
-
-import openllm
-
-
-START_COMMENT = f"\n"
-END_COMMENT = f"\n"
-
-ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-def main() -> int:
- with open(os.path.join(ROOT, "pyproject.toml"), "r") as f:
- deps = tomlkit.parse(f.read()).value["project"]["optional-dependencies"]
-
- with open(os.path.join(ROOT, "README.md"), "r") as f:
- readme = f.readlines()
-
- start_index, stop_index = readme.index(START_COMMENT), readme.index(END_COMMENT)
- formatted: dict[t.Literal["Model", "CPU", "GPU", "URL", "Installation", "Model Ids"], list[str | list[str]]] = {
- "Model": [],
- "URL": [],
- "CPU": [],
- "GPU": [],
- "Installation": [],
- "Model Ids": [],
- }
- max_install_len_div = 0
- for name, config_cls in openllm.CONFIG_MAPPING.items():
- dashed = inflection.dasherize(name)
- formatted["Model"].append(dashed)
- formatted["URL"].append(config_cls.__openllm_url__)
- formatted["GPU"].append("✅")
- formatted["CPU"].append("✅" if not config_cls.__openllm_requires_gpu__ else "❌")
- formatted["Model Ids"].append(config_cls.__openllm_model_ids__)
- if dashed in deps:
- instruction = f'```bash\npip install "openllm[{dashed}]"\n```'
- else:
- instruction = "```bash\npip install openllm\n```"
- if len(instruction) > max_install_len_div:
- max_install_len_div = len(instruction)
- formatted["Installation"].append(instruction)
-
- meta: list[str] = ["\n", "\n"]
-
- # NOTE: headers
- meta += ["\n"]
- meta.extend([f"{header} | \n" for header in formatted.keys() if header not in ("URL",)])
- meta += [" \n"]
- # NOTE: rows
- for name, url, cpu, gpu, installation, model_ids in t.cast(
- t.Iterable[t.Tuple[str, str, str, str, str, t.List[str]]], zip(*formatted.values())
- ):
- meta += "\n"
- meta.extend(
- [
- f"\n{name} | \n",
- f"{cpu} | \n",
- f"{gpu} | \n",
- f"\n\n{installation}\n\n | \n",
- ]
- )
- format_with_links: list[str] = []
- for lid in model_ids:
- format_with_links.append(f"{lid} ")
- meta.append("\n\n" + "\n".join(format_with_links) + " \n\n | \n")
- meta += " \n"
- meta.extend([" \n", "\n"])
-
- readme = readme[:start_index] + [START_COMMENT] + meta + [END_COMMENT] + readme[stop_index + 1 :]
-
- with open(os.path.join(ROOT, "README.md"), "w") as f:
- f.writelines(readme)
-
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/commune/modules/archive/openllm/tools/write-coverage-report.py b/commune/modules/archive/openllm/tools/write-coverage-report.py
deleted file mode 100755
index 0fd555509..000000000
--- a/commune/modules/archive/openllm/tools/write-coverage-report.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 BentoML Team. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import annotations
-
-from decimal import ROUND_DOWN
-from decimal import Decimal
-from pathlib import Path
-
-import orjson
-
-
-PRECISION = Decimal(".01")
-
-ROOT = Path(__file__).resolve().parent.parent
-
-
-def main():
- coverage_summary = ROOT / "coverage-summary.json"
-
- coverage_data = orjson.loads(coverage_summary.read_text(encoding="utf-8"))
- total_data = coverage_data.pop("total")
-
- lines = [
- "\n",
- "Package | Statements\n",
- "------- | ----------\n",
- ]
-
- for package, data in sorted(coverage_data.items()):
- statements_covered = data["statements_covered"]
- statements = data["statements"]
-
- rate = Decimal(statements_covered) / Decimal(statements) * 100
- rate = rate.quantize(PRECISION, rounding=ROUND_DOWN)
- lines.append(
- f"{package} | {100 if rate == 100 else rate}% ({statements_covered} / {statements})\n" # noqa: PLR2004
- )
-
- total_statements_covered = total_data["statements_covered"]
- total_statements = total_data["statements"]
- total_rate = Decimal(total_statements_covered) / Decimal(total_statements) * 100
- total_rate = total_rate.quantize(PRECISION, rounding=ROUND_DOWN)
- color = "ok" if float(total_rate) >= 95 else "critical"
- lines.insert(0, f"![Code Coverage](https://img.shields.io/badge/coverage-{total_rate}%25-{color}?style=flat)\n")
-
- lines.append(
- f"**Summary** | {100 if total_rate == 100 else total_rate}% "
- f"({total_statements_covered} / {total_statements})\n"
- )
-
- coverage_report = ROOT / "coverage-report.md"
- with coverage_report.open("w", encoding="utf-8") as f:
- f.write("".join(lines))
- return 0
-
-
-if __name__ == "__main__":
- raise SystemExit(main())
diff --git a/commune/modules/archive/openllm/typings/attr/__init__.pyi b/commune/modules/archive/openllm/typings/attr/__init__.pyi
deleted file mode 100644
index 7088e4231..000000000
--- a/commune/modules/archive/openllm/typings/attr/__init__.pyi
+++ /dev/null
@@ -1,512 +0,0 @@
-from __future__ import annotations
-
-import enum
-import sys
-from typing import Any
-from typing import Callable
-from typing import Dict
-from typing import Generic
-from typing import List
-from typing import Literal
-from typing import Mapping
-from typing import Optional
-from typing import ParamSpec
-from typing import Protocol
-from typing import Sequence
-from typing import Tuple
-from typing import Type
-from typing import TypeGuard
-from typing import TypeVar
-from typing import Union
-from typing import overload
-
-from . import converters as converters
-from . import exceptions as exceptions
-from . import filters as filters
-from . import setters as setters
-from . import validators as validators
-from ._cmp import cmp_using as cmp_using
-from ._typing_compat import AttrsInstance_
-from ._version_info import VersionInfo
-
-
-__version__: str
-__version_info__: VersionInfo
-__title__: str
-__description__: str
-__url__: str
-__uri__: str
-__author__: str
-__email__: str
-__license__: str
-__copyright__: str
-_T = TypeVar("_T")
-_C = TypeVar("_C", bound=type)
-_P = ParamSpec("_P")
-_EqOrderType = Union[bool, Callable[[Any], Any]]
-_ValidatorType = Callable[[Any, "Attribute[_T]", _T], Any]
-_ConverterType = Callable[[Any], Any]
-_FilterType = Callable[["Attribute[_T]", _T], bool]
-_ReprType = Callable[[Any], str]
-_ReprArgType = Union[bool, _ReprType]
-_OnSetAttrType = Callable[[Any, "Attribute[Any]", Any], Any]
-_OnSetAttrArgType = Union[_OnSetAttrType, List[_OnSetAttrType], setters._NoOpType]
-_FieldTransformer = Callable[[type, List["Attribute[Any]"]], List["Attribute[Any]"]]
-_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]]
-
-class ReprProtocol(Protocol):
- def __call__(__self, self: Any) -> str: ...
-
-class AttrsInstance(AttrsInstance_, Protocol): ...
-
-_A = TypeVar("_A", bound=AttrsInstance)
-
-class _Nothing(enum.Enum):
- NOTHING = ...
-
-NOTHING = ...
-if sys.version_info >= (3, 8):
- @overload
- def Factory(factory: Callable[[], _T]) -> _T: ...
- @overload
- def Factory(factory: Callable[[Any], _T], takes_self: Literal[True]) -> _T: ...
- @overload
- def Factory(factory: Callable[[], _T], takes_self: Literal[False]) -> _T: ...
-
-def __dataclass_transform__(
- *,
- eq_default: bool = ...,
- order_default: bool = ...,
- kw_only_default: bool = ...,
- frozen_default: bool = ...,
- field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = ...,
-) -> Callable[[_T], _T]: ...
-
-class _CountingAttr(Generic[_T]):
- counter: int
- _default: _T
- repr: _ReprArgType
- cmp: _EqOrderType
- eq: _EqOrderType
- eq_key: str
- order: _EqOrderType
- order_key: str
- hash: Optional[bool]
- init: bool
- converter: Optional[_ConverterType]
- metadata: Dict[Any, Any]
- _validator: Optional[_ValidatorType[_T]]
- type: Optional[Type[_T]]
- kw_only: bool
- on_setattr: _OnSetAttrType
- alias: Optional[str]
-
-class Attribute(Generic[_T]):
- name: str
- default: Optional[_T]
- validator: Optional[_ValidatorType[_T]]
- repr: _ReprArgType
- cmp: _EqOrderType
- eq: _EqOrderType
- order: _EqOrderType
- hash: Optional[bool]
- init: bool
- converter: Optional[_ConverterType]
- metadata: Dict[Any, Any]
- type: Optional[Type[_T]]
- kw_only: bool
- on_setattr: _OnSetAttrType
- alias: Optional[str]
- def evolve(self, **changes: Any) -> Attribute[Any]: ...
- @classmethod
- def from_counting_attr(cls, name: str, ca: _CountingAttr[_T], type: type[Any] | None = None) -> Attribute[_T]: ...
-
-@overload
-def attrib(
- default: None = ...,
- validator: None = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: None = ...,
- converter: None = ...,
- factory: None = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
-) -> Any: ...
-@overload
-def attrib(
- default: None = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: Optional[Type[_T]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
-) -> _T: ...
-@overload
-def attrib(
- default: _T,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: Optional[Type[_T]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
-) -> _T: ...
-@overload
-def attrib(
- default: Optional[_T] = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- type: object = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
-) -> Any: ...
-@overload
-def field(
- *,
- default: None = ...,
- validator: None = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: None = ...,
- factory: None = ...,
- kw_only: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
- type: Optional[type] = ...,
-) -> Any: ...
-@overload
-def field(
- *,
- default: None = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
- type: Optional[type] = ...,
-) -> _T: ...
-@overload
-def field(
- *,
- default: _T,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
- type: Optional[type] = ...,
-) -> _T: ...
-@overload
-def field(
- *,
- default: Optional[_T] = ...,
- validator: Optional[_ValidatorArgType[_T]] = ...,
- repr: _ReprArgType = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- metadata: Optional[Mapping[Any, Any]] = ...,
- converter: Optional[_ConverterType] = ...,
- factory: Optional[Callable[[], _T]] = ...,
- kw_only: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- alias: Optional[str] = ...,
- type: Optional[type] = ...,
-) -> Any: ...
-@overload
-@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
-def attrs(
- maybe_cls: _C,
- these: Optional[Dict[str, Any]] = ...,
- repr_ns: Optional[str] = ...,
- repr: bool = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- auto_detect: bool = ...,
- collect_by_mro: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
- match_args: bool = ...,
- unsafe_hash: Optional[bool] = ...,
-) -> _C: ...
-@overload
-@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
-def attrs(
- maybe_cls: None = ...,
- these: Optional[Dict[str, Any]] = ...,
- repr_ns: Optional[str] = ...,
- repr: bool = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- auto_detect: bool = ...,
- collect_by_mro: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
- match_args: bool = ...,
- unsafe_hash: Optional[bool] = ...,
-) -> Callable[[_C], _C]: ...
-@overload
-@__dataclass_transform__(field_descriptors=(attrib, field))
-def define(
- maybe_cls: _C,
- *,
- these: Optional[Dict[str, Any]] = ...,
- repr: bool = ...,
- unsafe_hash: Optional[bool] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- auto_detect: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
- match_args: bool = ...,
-) -> _C: ...
-@overload
-@__dataclass_transform__(field_descriptors=(attrib, field))
-def define(
- maybe_cls: None = ...,
- *,
- these: Optional[Dict[str, Any]] = ...,
- repr: bool = ...,
- unsafe_hash: Optional[bool] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- auto_detect: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
- match_args: bool = ...,
-) -> Callable[[_C], _C]: ...
-
-mutable = ...
-
-@overload
-@__dataclass_transform__(frozen_default=True, field_descriptors=(attrib, field))
-def frozen(
- maybe_cls: _C,
- *,
- these: Optional[Dict[str, Any]] = ...,
- repr: bool = ...,
- unsafe_hash: Optional[bool] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- auto_detect: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
- match_args: bool = ...,
-) -> _C: ...
-@overload
-@__dataclass_transform__(frozen_default=True, field_descriptors=(attrib, field))
-def frozen(
- maybe_cls: None = ...,
- *,
- these: Optional[Dict[str, Any]] = ...,
- repr: bool = ...,
- unsafe_hash: Optional[bool] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[bool] = ...,
- order: Optional[bool] = ...,
- auto_detect: bool = ...,
- getstate_setstate: Optional[bool] = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
- match_args: bool = ...,
-) -> Callable[[_C], _C]: ...
-def fields(cls: Type[AttrsInstance]) -> Any: ...
-def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ...
-def validate(inst: AttrsInstance) -> None: ...
-def resolve_types(
- cls: _A,
- globalns: Optional[Dict[str, Any]] = ...,
- localns: Optional[Dict[str, Any]] = ...,
- attribs: Optional[List[Attribute[Any]]] = ...,
- include_extras: bool = ...,
-) -> _A: ...
-def make_class(
- name: str,
- attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]],
- bases: Tuple[type, ...] = ...,
- repr_ns: Optional[str] = ...,
- repr: bool = ...,
- cmp: Optional[_EqOrderType] = ...,
- hash: Optional[bool] = ...,
- init: bool = ...,
- slots: bool = ...,
- frozen: bool = ...,
- weakref_slot: bool = ...,
- str: bool = ...,
- auto_attribs: bool = ...,
- kw_only: bool = ...,
- cache_hash: bool = ...,
- auto_exc: bool = ...,
- eq: Optional[_EqOrderType] = ...,
- order: Optional[_EqOrderType] = ...,
- collect_by_mro: bool = ...,
- on_setattr: Optional[_OnSetAttrArgType] = ...,
- field_transformer: Optional[_FieldTransformer] = ...,
-) -> type: ...
-def asdict(
- inst: AttrsInstance,
- recurse: bool = ...,
- filter: Optional[_FilterType[Any]] = ...,
- dict_factory: Type[Mapping[Any, Any]] = ...,
- retain_collection_types: bool = ...,
- value_serializer: Optional[Callable[[type, Attribute[Any], Any], Any]] = ...,
- tuple_keys: Optional[bool] = ...,
-) -> Dict[str, Any]: ...
-def astuple(
- inst: AttrsInstance,
- recurse: bool = ...,
- filter: Optional[_FilterType[Any]] = ...,
- tuple_factory: Type[Sequence[Any]] = ...,
- retain_collection_types: bool = ...,
-) -> Tuple[Any, ...]: ...
-def has(cls: type) -> TypeGuard[Type[AttrsInstance]]: ...
-def assoc(inst: _T, **changes: Any) -> _T: ...
-def evolve(inst: _T, **changes: Any) -> _T: ...
-def set_run_validators(run: bool) -> None: ...
-def get_run_validators() -> bool: ...
-
-attributes = ...
-attr = ...
-dataclass = ...
-
-def _make_init(
- cls: type[AttrsInstance],
- attrs: tuple[Attribute[Any]],
- pre_init: bool,
- post_init: bool,
- frozen: bool,
- slots: bool,
- cache_hash: bool,
- base_attr_map: dict[str, Any],
- is_exc: bool,
- cls_on_setattr: Any,
- attrs_init: bool,
-) -> Callable[_P, Any]: ...
-def _make_method(name: str, script: str, filename: str, globs: dict[str, Any]) -> Callable[..., Any]: ...
-def _make_repr(attrs: tuple[Attribute[Any]], ns: str | None, cls: AttrsInstance) -> ReprProtocol: ...
-def _transform_attrs(
- cls: type[AttrsInstance],
- these: dict[str, _CountingAttr[_T]] | None,
- auto_attribs: bool,
- kw_only: bool,
- collect_by_mro: bool,
- field_transformer: Optional[_FieldTransformer],
-) -> tuple[tuple[attr.Attribute[Any], ...], tuple[attr.Attribute[Any], ...], dict[attr.Attribute[Any], type[Any]]]: ...
diff --git a/commune/modules/archive/openllm/typings/attr/_cmp.pyi b/commune/modules/archive/openllm/typings/attr/_cmp.pyi
deleted file mode 100644
index 815beb98a..000000000
--- a/commune/modules/archive/openllm/typings/attr/_cmp.pyi
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import Any
-from typing import Callable
-from typing import Optional
-
-
-_CompareWithType = Callable[[Any, Any], bool]
-
-def cmp_using(
- eq: Optional[_CompareWithType] = ...,
- lt: Optional[_CompareWithType] = ...,
- le: Optional[_CompareWithType] = ...,
- gt: Optional[_CompareWithType] = ...,
- ge: Optional[_CompareWithType] = ...,
- require_same_type: bool = ...,
- class_name: str = ...,
-) -> type[Any]: ...
diff --git a/commune/modules/archive/openllm/typings/attr/_compat.pyi b/commune/modules/archive/openllm/typings/attr/_compat.pyi
deleted file mode 100644
index 5ba750e3f..000000000
--- a/commune/modules/archive/openllm/typings/attr/_compat.pyi
+++ /dev/null
@@ -1,5 +0,0 @@
-import threading
-
-
-set_closure_cell = ...
-repr_context: threading.local = ...
diff --git a/commune/modules/archive/openllm/typings/attr/_typing_compat.pyi b/commune/modules/archive/openllm/typings/attr/_typing_compat.pyi
deleted file mode 100644
index 168e0110f..000000000
--- a/commune/modules/archive/openllm/typings/attr/_typing_compat.pyi
+++ /dev/null
@@ -1,14 +0,0 @@
-from typing import Any
-from typing import ClassVar
-from typing import Protocol
-
-
-MYPY = False
-
-if MYPY:
- class AttrsInstance_(Protocol):
- __attrs_attrs__: ClassVar[Any]
- ...
-
-else:
- class AttrsInstance_(Protocol): ...
diff --git a/commune/modules/archive/openllm/typings/attr/_version_info.pyi b/commune/modules/archive/openllm/typings/attr/_version_info.pyi
deleted file mode 100644
index 45ced0863..000000000
--- a/commune/modules/archive/openllm/typings/attr/_version_info.pyi
+++ /dev/null
@@ -1,9 +0,0 @@
-class VersionInfo:
- @property
- def year(self) -> int: ...
- @property
- def minor(self) -> int: ...
- @property
- def micro(self) -> int: ...
- @property
- def releaselevel(self) -> str: ...
diff --git a/commune/modules/archive/openllm/typings/attr/converters.pyi b/commune/modules/archive/openllm/typings/attr/converters.pyi
deleted file mode 100644
index c00572071..000000000
--- a/commune/modules/archive/openllm/typings/attr/converters.pyi
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import Callable
-from typing import TypeVar
-from typing import overload
-
-from . import _ConverterType
-
-
-_T = TypeVar("_T")
-
-def pipe(*validators: _ConverterType) -> _ConverterType: ...
-def optional(converter: _ConverterType) -> _ConverterType: ...
-@overload
-def default_if_none(default: _T) -> _ConverterType: ...
-@overload
-def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ...
-def to_bool(val: str) -> bool: ...
diff --git a/commune/modules/archive/openllm/typings/attr/exceptions.pyi b/commune/modules/archive/openllm/typings/attr/exceptions.pyi
deleted file mode 100644
index a800fb26b..000000000
--- a/commune/modules/archive/openllm/typings/attr/exceptions.pyi
+++ /dev/null
@@ -1,18 +0,0 @@
-from typing import Any
-
-
-class FrozenError(AttributeError):
- msg: str = ...
-
-class FrozenInstanceError(FrozenError): ...
-class FrozenAttributeError(FrozenError): ...
-class AttrsAttributeNotFoundError(ValueError): ...
-class NotAnAttrsClassError(ValueError): ...
-class DefaultAlreadySetError(RuntimeError): ...
-class UnannotatedAttributeError(RuntimeError): ...
-class PythonTooOldError(RuntimeError): ...
-
-class NotCallableError(TypeError):
- msg: str = ...
- value: Any = ...
- def __init__(self, msg: str, value: Any) -> None: ...
diff --git a/commune/modules/archive/openllm/typings/attr/filters.pyi b/commune/modules/archive/openllm/typings/attr/filters.pyi
deleted file mode 100644
index 346be4012..000000000
--- a/commune/modules/archive/openllm/typings/attr/filters.pyi
+++ /dev/null
@@ -1,9 +0,0 @@
-from typing import Any
-from typing import Union
-
-from . import Attribute
-from . import _FilterType
-
-
-def include(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ...
-def exclude(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ...
diff --git a/commune/modules/archive/openllm/typings/attr/setters.pyi b/commune/modules/archive/openllm/typings/attr/setters.pyi
deleted file mode 100644
index eee98de5c..000000000
--- a/commune/modules/archive/openllm/typings/attr/setters.pyi
+++ /dev/null
@@ -1,18 +0,0 @@
-from typing import Any
-from typing import NewType
-from typing import NoReturn
-from typing import TypeVar
-
-from . import Attribute
-from . import _OnSetAttrType
-
-
-_T = TypeVar("_T")
-
-def frozen(instance: Any, attribute: Attribute[Any], new_value: Any) -> NoReturn: ...
-def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ...
-def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ...
-def convert(instance: Any, attribute: Attribute[Any], new_value: Any) -> Any: ...
-
-_NoOpType = NewType("_NoOpType", object)
-NO_OP: _NoOpType
diff --git a/commune/modules/archive/openllm/typings/attr/validators.pyi b/commune/modules/archive/openllm/typings/attr/validators.pyi
deleted file mode 100644
index 922758476..000000000
--- a/commune/modules/archive/openllm/typings/attr/validators.pyi
+++ /dev/null
@@ -1,75 +0,0 @@
-from typing import Any
-from typing import AnyStr
-from typing import Callable
-from typing import Container
-from typing import ContextManager
-from typing import Iterable
-from typing import List
-from typing import Mapping
-from typing import Match
-from typing import Optional
-from typing import Pattern
-from typing import Tuple
-from typing import Type
-from typing import TypeVar
-from typing import Union
-from typing import overload
-
-from . import _ValidatorArgType
-from . import _ValidatorType
-
-
-_T = TypeVar("_T")
-_T1 = TypeVar("_T1")
-_T2 = TypeVar("_T2")
-_T3 = TypeVar("_T3")
-_I = TypeVar("_I", bound=Iterable)
-_K = TypeVar("_K")
-_V = TypeVar("_V")
-_M = TypeVar("_M", bound=Mapping)
-
-def set_disabled(run: bool) -> None: ...
-def get_disabled() -> bool: ...
-def disabled() -> ContextManager[None]: ...
-@overload
-def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ...
-@overload
-def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ...
-@overload
-def instance_of(type: Tuple[Type[_T1], Type[_T2]]) -> _ValidatorType[Union[_T1, _T2]]: ...
-@overload
-def instance_of(type: Tuple[Type[_T1], Type[_T2], Type[_T3]]) -> _ValidatorType[Union[_T1, _T2, _T3]]: ...
-@overload
-def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
-def provides(interface: Any) -> _ValidatorType[Any]: ...
-def optional(
- validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T]]]
-) -> _ValidatorType[Optional[_T]]: ...
-def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
-def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
-def matches_re(
- regex: Union[Pattern[AnyStr], AnyStr],
- flags: int = ...,
- func: Optional[Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]]] = ...,
-) -> _ValidatorType[AnyStr]: ...
-def deep_iterable(
- member_validator: _ValidatorArgType[_T], iterable_validator: Optional[_ValidatorType[_I]] = ...
-) -> _ValidatorType[_I]: ...
-def deep_mapping(
- key_validator: _ValidatorType[_K],
- value_validator: _ValidatorType[_V],
- mapping_validator: Optional[_ValidatorType[_M]] = ...,
-) -> _ValidatorType[_M]: ...
-def is_callable() -> _ValidatorType[_T]: ...
-def lt(val: _T) -> _ValidatorType[_T]: ...
-def le(val: _T) -> _ValidatorType[_T]: ...
-def ge(val: _T) -> _ValidatorType[_T]: ...
-def gt(val: _T) -> _ValidatorType[_T]: ...
-def max_len(length: int) -> _ValidatorType[_T]: ...
-def min_len(length: int) -> _ValidatorType[_T]: ...
-def not_(
- validator: _ValidatorType[_T],
- *,
- msg: Optional[str] = ...,
- exc_types: Union[Type[Exception], Iterable[Type[Exception]]] = ...,
-) -> _ValidatorType[_T]: ...
diff --git a/commune/modules/archive/openllm/typings/click_option_group/__init__.pyi b/commune/modules/archive/openllm/typings/click_option_group/__init__.pyi
deleted file mode 100644
index 9ea0a6541..000000000
--- a/commune/modules/archive/openllm/typings/click_option_group/__init__.pyi
+++ /dev/null
@@ -1,31 +0,0 @@
-from ._core import AllOptionGroup
-from ._core import GroupedOption
-from ._core import MutuallyExclusiveOptionGroup
-from ._core import OptionGroup
-from ._core import RequiredAllOptionGroup
-from ._core import RequiredAnyOptionGroup
-from ._core import RequiredMutuallyExclusiveOptionGroup
-from ._decorators import optgroup
-from ._version import __version__
-
-
-"""
-click-option-group
-~~~~~~~~~~~~~~~~~~
-
-Option groups missing in Click
-
-:copyright: © 2019-2020 by Eugene Prilepin
-:license: BSD, see LICENSE for more details.
-"""
-__all__ = [
- "__version__",
- "optgroup",
- "GroupedOption",
- "OptionGroup",
- "RequiredAnyOptionGroup",
- "AllOptionGroup",
- "RequiredAllOptionGroup",
- "MutuallyExclusiveOptionGroup",
- "RequiredMutuallyExclusiveOptionGroup",
-]
diff --git a/commune/modules/archive/openllm/typings/click_option_group/_core.pyi b/commune/modules/archive/openllm/typings/click_option_group/_core.pyi
deleted file mode 100644
index 796a6726f..000000000
--- a/commune/modules/archive/openllm/typings/click_option_group/_core.pyi
+++ /dev/null
@@ -1,162 +0,0 @@
-from collections.abc import Callable
-from typing import Any
-from typing import Dict
-from typing import List
-from typing import Mapping
-from typing import Optional
-from typing import Sequence
-from typing import Set
-from typing import Tuple
-from typing import Union
-
-import click
-
-
-FC = Union[Callable[..., Any], click.Command]
-
-class GroupedOption(click.Option):
- """Represents grouped (related) optional values
-
- The class should be used only with `OptionGroup` class for creating grouped options.
-
- :param param_decls: option declaration tuple
- :param group: `OptionGroup` instance (the group for this option)
- :param attrs: additional option attributes
- """
-
- def __init__(self, param_decls: Optional[Sequence[str]] = ..., *, group: OptionGroup, **attrs: Any) -> None: ...
- @property
- def group(self) -> OptionGroup:
- """Returns the reference to the group for this option
-
- :return: `OptionGroup` the group instance for this option
- """
- ...
- def handle_parse_result(
- self, ctx: click.Context, opts: Mapping[str, Any], args: List[str]
- ) -> Tuple[Any, List[str]]: ...
- def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]: ...
-
-class _GroupTitleFakeOption(click.Option):
- """The helper `Option` class to display option group title in help"""
-
- def __init__(self, param_decls: Optional[Sequence[str]] = ..., *, group: OptionGroup, **attrs: Any) -> None: ...
- def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]: ...
-
-class OptionGroup:
- """Option group manages grouped (related) options
-
- The class is used for creating the groups of options. The class can de used as based class to implement
- specific behavior for grouped options.
-
- :param name: the group name. If it is not set the default group name will be used
- :param help: the group help text or None
- """
-
- def __init__(self, name: Optional[str] = ..., *, hidden: bool = ..., help: Optional[str] = ...) -> None: ...
- @property
- def name(self) -> str:
- """Returns the group name or empty string if it was not set
-
- :return: group name
- """
- ...
- @property
- def help(self) -> str:
- """Returns the group help or empty string if it was not set
-
- :return: group help
- """
- ...
- @property
- def name_extra(self) -> List[str]:
- """Returns extra name attributes for the group"""
- ...
- @property
- def forbidden_option_attrs(self) -> List[str]:
- """Returns the list of forbidden option attributes for the group"""
- ...
- def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]:
- """Returns the help record for the group
-
- :param ctx: Click Context object
- :return: the tuple of two fileds: `(name, help)`
- """
- ...
- def option(self, *param_decls: str, **attrs: Any) -> Callable:
- """Decorator attaches an grouped option to the command
-
- The decorator is used for adding options to the group and to the Click-command
- """
- ...
- def get_options(self, ctx: click.Context) -> Dict[str, GroupedOption]:
- """Returns the dictionary with group options"""
- ...
- def get_option_names(self, ctx: click.Context) -> List[str]:
- """Returns the list with option names ordered by addition in the group"""
- ...
- def get_error_hint(self, ctx: click.Context, option_names: Optional[Set[str]] = ...) -> str: ...
- def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: Mapping[str, Any]) -> None:
- """The method should be used for adding specific behavior and relation for options in the group"""
- ...
-
-class RequiredAnyOptionGroup(OptionGroup):
- """Option group with required any options of this group
-
- `RequiredAnyOptionGroup` defines the behavior: At least one option from the group must be set.
- """
-
- @property
- def forbidden_option_attrs(self) -> List[str]: ...
- @property
- def name_extra(self) -> List[str]: ...
- def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: Mapping[str, Any]) -> None: ...
-
-class RequiredAllOptionGroup(OptionGroup):
- """Option group with required all options of this group
-
- `RequiredAllOptionGroup` defines the behavior: All options from the group must be set.
- """
-
- @property
- def forbidden_option_attrs(self) -> List[str]: ...
- @property
- def name_extra(self) -> List[str]: ...
- def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: Mapping[str, Any]) -> None: ...
-
-class MutuallyExclusiveOptionGroup(OptionGroup):
- """Option group with mutually exclusive behavior for grouped options
-
- `MutuallyExclusiveOptionGroup` defines the behavior:
- - Only one or none option from the group must be set
- """
-
- @property
- def forbidden_option_attrs(self) -> List[str]: ...
- @property
- def name_extra(self) -> List[str]: ...
- def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: Mapping[str, Any]) -> None: ...
-
-class RequiredMutuallyExclusiveOptionGroup(MutuallyExclusiveOptionGroup):
- """Option group with required and mutually exclusive behavior for grouped options
-
- `RequiredMutuallyExclusiveOptionGroup` defines the behavior:
- - Only one required option from the group must be set
- """
-
- @property
- def name_extra(self) -> List[str]: ...
- def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: Mapping[str, Any]) -> None: ...
-
-class AllOptionGroup(OptionGroup):
- """Option group with required all/none options of this group
-
- `AllOptionGroup` defines the behavior:
- - All options from the group must be set or None must be set
- """
-
- @property
- def forbidden_option_attrs(self) -> List[str]: ...
- @property
- def name_extra(self) -> List[str]: ...
- def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: Mapping[str, Any]) -> None: ...
diff --git a/commune/modules/archive/openllm/typings/click_option_group/_decorators.pyi b/commune/modules/archive/openllm/typings/click_option_group/_decorators.pyi
deleted file mode 100644
index 6dfae268d..000000000
--- a/commune/modules/archive/openllm/typings/click_option_group/_decorators.pyi
+++ /dev/null
@@ -1,113 +0,0 @@
-from typing import Any
-from typing import Callable
-from typing import Dict
-from typing import Generic
-from typing import NamedTuple
-from typing import Optional
-from typing import ParamSpec
-from typing import Protocol
-from typing import Tuple
-from typing import Type
-from typing import TypeVar
-
-import click
-
-from ._core import FC
-from ._core import OptionGroup
-
-
-P = ParamSpec("P")
-O_co = TypeVar("O_co", covariant=True)
-
-F = Callable[P, O_co]
-
-class OptionStackItem(NamedTuple):
- param_decls: Tuple[str, ...]
- attrs: Dict[str, Any]
- param_count: int
- ...
-
-class ClickFunctionWrapper(Protocol[P, O_co]):
- __name__: str
- __click_params__: list[click.Option]
-
- def __call__(self, *args: P.args, **kwargs: P.kwargs) -> O_co: ...
-
-class _NotAttachedOption(click.Option):
- """The helper class to catch grouped options which were not attached to the group
-
- Raises TypeError if not attached options exist.
- """
-
- def __init__(self, param_decls: Any = ..., *, all_not_attached_options: Any, **attrs: Any) -> None: ...
- def handle_parse_result(self, ctx: click.Context, opts: Any, args: tuple[Any]) -> Any: ...
-
-class _OptGroup(Generic[O_co]):
- """A helper class to manage creating groups and group options via decorators
-
- The class provides two decorator-methods: `group`/`__call__` and `option`.
- These decorators should be used for adding grouped options. The class have
- single global instance `optgroup` that should be used in most cases.
-
- The example of usage::
-
- ...
- @optgroup('Group 1', help='option group 1')
- @optgroup.option('--foo')
- @optgroup.option('--bar')
- @optgroup.group('Group 2', help='option group 2')
- @optgroup.option('--spam')
- ...
- """
-
- def __init__(self) -> None: ...
- def __call__(
- self,
- name: Optional[str] = ...,
- *,
- help: Optional[str] = ...,
- cls: Optional[Type[OptionGroup]] = ...,
- **attrs: Any,
- ) -> FC:
- """Creates a new group and collects its options
-
- Creates the option group and registers all grouped options
- which were added by `option` decorator.
-
- :param name: Group name or None for default name
- :param help: Group help or None for empty help
- :param cls: Option group class that should be inherited from `OptionGroup` class
- :param attrs: Additional parameters of option group class
- """
- ...
- def group(
- self,
- name: Optional[str] = ...,
- *,
- help: Optional[str] = ...,
- cls: Optional[Type[OptionGroup]] = ...,
- **attrs: Any,
- ) -> FC:
- """The decorator creates a new group and collects its options
-
- Creates the option group and registers all grouped options
- which were added by `option` decorator.
-
- :param name: Group name or None for default name
- :param help: Group help or None for empty help
- :param cls: Option group class that should be inherited from `OptionGroup` class
- :param attrs: Additional parameters of option group class
- """
- ...
- def option(self, *param_decls: Any, **attrs: Any) -> FC:
- """The decorator adds a new option to the group
-
- The decorator is lazy. It adds option decls and attrs.
- All options will be registered by `group` decorator.
-
- :param param_decls: option declaration tuple
- :param attrs: additional option attributes and parameters
- """
- ...
-
-optgroup: _OptGroup[Any] = ...
diff --git a/commune/modules/archive/openllm/typings/click_option_group/_helpers.pyi b/commune/modules/archive/openllm/typings/click_option_group/_helpers.pyi
deleted file mode 100644
index bdf029c82..000000000
--- a/commune/modules/archive/openllm/typings/click_option_group/_helpers.pyi
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-This type stub file was generated by pyright.
-"""
-
-import collections.abc as abc
-from typing import List
-from typing import Tuple
-
-import click
-
-
-FAKE_OPT_NAME_LEN = ...
-
-def get_callback_and_params(func) -> Tuple[abc.Callable, List[click.Option]]:
- """Returns callback function and its parameters list
-
- :param func: decorated function or click Command
- :return: (callback, params)
- """
- ...
-
-def get_fake_option_name(name_len: int = ..., prefix: str = ...): ...
-def raise_mixing_decorators_error(wrong_option: click.Option, callback: abc.Callable): ...
-def resolve_wrappers(f):
- """Get the underlying function behind any level of function wrappers."""
- ...
diff --git a/commune/modules/archive/openllm/typings/click_option_group/_version.pyi b/commune/modules/archive/openllm/typings/click_option_group/_version.pyi
deleted file mode 100644
index fc797c9a6..000000000
--- a/commune/modules/archive/openllm/typings/click_option_group/_version.pyi
+++ /dev/null
@@ -1,5 +0,0 @@
-"""
-This type stub file was generated by pyright.
-"""
-
-__version__ = ...
diff --git a/commune/modules/archive/openllm/typings/deepmerge/__init__.pyi b/commune/modules/archive/openllm/typings/deepmerge/__init__.pyi
deleted file mode 100644
index d3636bcc0..000000000
--- a/commune/modules/archive/openllm/typings/deepmerge/__init__.pyi
+++ /dev/null
@@ -1,14 +0,0 @@
-from typing import List
-from typing import Literal
-from typing import Tuple
-from typing import Union
-
-from .merger import Merger
-
-
-DEFAULT_TYPE_SPECIFIC_MERGE_STRATEGIES: List[
- Tuple[type, Union[Literal["append"], Literal["merge"], Literal["union"]]]
-] = ...
-always_merger: Merger = ...
-merge_or_raise: Merger = ...
-conservative_merger: Merger = ...
diff --git a/commune/modules/archive/openllm/typings/deepmerge/merger.pyi b/commune/modules/archive/openllm/typings/deepmerge/merger.pyi
deleted file mode 100644
index c5a86d3f4..000000000
--- a/commune/modules/archive/openllm/typings/deepmerge/merger.pyi
+++ /dev/null
@@ -1,26 +0,0 @@
-from typing import Any
-from typing import Dict
-from typing import List
-from typing import Tuple
-from typing import Union
-
-from .strategy.core import StrategyList
-from .strategy.dict import DictStrategies
-from .strategy.list import ListStrategies
-from .strategy.set import SetStrategies
-
-
-ConfigDictType = Dict[str, Any]
-
-class Merger:
- PROVIDED_TYPE_STRATEGIES: Dict[type, Union[ListStrategies, DictStrategies, SetStrategies]] = ...
-
- def __init__(
- self,
- type_strategies: List[Tuple[type, str]],
- fallback_strategies: List[str],
- type_conflict_strategies: List[str],
- ) -> None: ...
- def merge(self, base: ConfigDictType, nxt: ConfigDictType) -> ConfigDictType: ...
- def type_conflict_strategy(self, *args: Any) -> Any: ...
- def value_strategy(self, path: str, base: StrategyList, nxt: StrategyList) -> None: ...
diff --git a/commune/modules/archive/openllm/typings/deepmerge/strategy/core.pyi b/commune/modules/archive/openllm/typings/deepmerge/strategy/core.pyi
deleted file mode 100644
index ac34c78aa..000000000
--- a/commune/modules/archive/openllm/typings/deepmerge/strategy/core.pyi
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import Any
-from typing import Callable
-from typing import List
-from typing import Optional
-from typing import Union
-
-
-_StringOrFunction = Union[str, Callable[..., Any]]
-STRATEGY_END: object = ...
-
-class StrategyList:
- NAME: Optional[str] = ...
- def __init__(self, strategy_list: Union[_StringOrFunction, List[_StringOrFunction]]) -> None: ...
- @classmethod
- def _expand_strategy(cls, strategy: _StringOrFunction) -> _StringOrFunction: ...
- def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
diff --git a/commune/modules/archive/openllm/typings/deepmerge/strategy/dict.pyi b/commune/modules/archive/openllm/typings/deepmerge/strategy/dict.pyi
deleted file mode 100644
index 382897c91..000000000
--- a/commune/modules/archive/openllm/typings/deepmerge/strategy/dict.pyi
+++ /dev/null
@@ -1,9 +0,0 @@
-from ..merger import Merger
-from .core import StrategyList
-
-
-class DictStrategies(StrategyList):
- @staticmethod
- def strategy_merge(config: Merger, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
- @staticmethod
- def strategy_override(config: Merger, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
diff --git a/commune/modules/archive/openllm/typings/deepmerge/strategy/list.pyi b/commune/modules/archive/openllm/typings/deepmerge/strategy/list.pyi
deleted file mode 100644
index c704d9cc3..000000000
--- a/commune/modules/archive/openllm/typings/deepmerge/strategy/list.pyi
+++ /dev/null
@@ -1,13 +0,0 @@
-from ..merger import Merger
-from .core import StrategyList
-
-
-class ListStrategies(StrategyList):
- NAME: str = ...
-
- @staticmethod
- def strategy_override(config: Merger, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
- @staticmethod
- def strategy_prepend(config: Merger, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
- @staticmethod
- def strategy_append(config: Merger, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
diff --git a/commune/modules/archive/openllm/typings/deepmerge/strategy/set.pyi b/commune/modules/archive/openllm/typings/deepmerge/strategy/set.pyi
deleted file mode 100644
index b49f2a4f6..000000000
--- a/commune/modules/archive/openllm/typings/deepmerge/strategy/set.pyi
+++ /dev/null
@@ -1,15 +0,0 @@
-from typing import Any
-
-from ..merger import Merger
-from .core import StrategyList
-
-
-class SetStrategies(StrategyList):
- NAME = ...
-
- @staticmethod
- def strategy_union(config: Any, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
- @staticmethod
- def strategy_intersect(config: Any, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
- @staticmethod
- def strategy_override(config: Merger, path: str, base: StrategyList, nxt: StrategyList) -> StrategyList: ...
diff --git a/commune/modules/archive/openllm/typings/rsmiBindings.pyi b/commune/modules/archive/openllm/typings/rsmiBindings.pyi
deleted file mode 100644
index 8889ecc73..000000000
--- a/commune/modules/archive/openllm/typings/rsmiBindings.pyi
+++ /dev/null
@@ -1,57 +0,0 @@
-# See https://github.com/RadeonOpenCompute/rocm_smi_lib/blob/master/python_smi_tools/rsmiBindings.py
-import ctypes
-from typing import LiteralString
-
-
-class rocmsmi(ctypes.CDLL):
- @staticmethod
- def rsmi_num_monitor_devices(num_devices: ctypes._CArgObject) -> LiteralString: ...
-
-# Device ID
-dv_id: ctypes.c_uint64 = ...
-# GPU ID
-gpu_id: ctypes.c_uint32 = ...
-
-# Policy enums
-RSMI_MAX_NUM_FREQUENCIES = 32
-RSMI_MAX_FAN_SPEED = 255
-RSMI_NUM_VOLTAGE_CURVE_POINTS = 3
-
-class rsmi_status_t(ctypes.c_int):
- RSMI_STATUS_SUCCESS = 0x0
- RSMI_STATUS_INVALID_ARGS = 0x1
- RSMI_STATUS_NOT_SUPPORTED = 0x2
- RSMI_STATUS_FILE_ERROR = 0x3
- RSMI_STATUS_PERMISSION = 0x4
- RSMI_STATUS_OUT_OF_RESOURCES = 0x5
- RSMI_STATUS_INTERNAL_EXCEPTION = 0x6
- RSMI_STATUS_INPUT_OUT_OF_BOUNDS = 0x7
- RSMI_STATUS_INIT_ERROR = 0x8
- RSMI_INITIALIZATION_ERROR = RSMI_STATUS_INIT_ERROR
- RSMI_STATUS_NOT_YET_IMPLEMENTED = 0x9
- RSMI_STATUS_NOT_FOUND = 0xA
- RSMI_STATUS_INSUFFICIENT_SIZE = 0xB
- RSMI_STATUS_INTERRUPT = 0xC
- RSMI_STATUS_UNEXPECTED_SIZE = 0xD
- RSMI_STATUS_NO_DATA = 0xE
- RSMI_STATUS_UNKNOWN_ERROR = 0xFFFFFFFF
-
-# Dictionary of rsmi ret codes and it's verbose output
-rsmi_status_verbose_err_out = {
- rsmi_status_t.RSMI_STATUS_SUCCESS: "Operation was successful",
- rsmi_status_t.RSMI_STATUS_INVALID_ARGS: "Invalid arguments provided",
- rsmi_status_t.RSMI_STATUS_NOT_SUPPORTED: "Not supported on the given system",
- rsmi_status_t.RSMI_STATUS_FILE_ERROR: "Problem accessing a file",
- rsmi_status_t.RSMI_STATUS_PERMISSION: "Permission denied",
- rsmi_status_t.RSMI_STATUS_OUT_OF_RESOURCES: "Unable to acquire memory or other resource",
- rsmi_status_t.RSMI_STATUS_INTERNAL_EXCEPTION: "An internal exception was caught",
- rsmi_status_t.RSMI_STATUS_INPUT_OUT_OF_BOUNDS: "Provided input is out of allowable or safe range",
- rsmi_status_t.RSMI_INITIALIZATION_ERROR: "Error occured during rsmi initialization",
- rsmi_status_t.RSMI_STATUS_NOT_YET_IMPLEMENTED: "Requested function is not implemented on this setup",
- rsmi_status_t.RSMI_STATUS_NOT_FOUND: "Item searched for but not found",
- rsmi_status_t.RSMI_STATUS_INSUFFICIENT_SIZE: "Insufficient resources available",
- rsmi_status_t.RSMI_STATUS_INTERRUPT: "Interrupt occured during execution",
- rsmi_status_t.RSMI_STATUS_UNEXPECTED_SIZE: "Unexpected amount of data read",
- rsmi_status_t.RSMI_STATUS_NO_DATA: "No data found for the given input",
- rsmi_status_t.RSMI_STATUS_UNKNOWN_ERROR: "Unknown error occured",
-}
diff --git a/commune/modules/archive/pool/pool.py b/commune/modules/archive/pool/pool.py
deleted file mode 100644
index 7bded6a09..000000000
--- a/commune/modules/archive/pool/pool.py
+++ /dev/null
@@ -1,219 +0,0 @@
-import queue
-import commune as c
-import threading
-import multiprocessing
-import asyncio
-
-
-class Pool(c.Module):
- def __init__(self,
- modules = None
- **kwargs):
-
-
- self.run_loop = True
- self.init(**kwargs)
- self.set_fn(fn)
- self.add_workers()
-
-
- def set_fn(self, fn):
- if fn is None:
- fn = self.default_fn
- self.fn = fn
- assert callable(self.fn)
- return fn
-
- def resolve_queue_name(self, name = None):
- if name is None:
- name = f'Q::{len(self.workers)}'
-
- assert isinstance(name, str)
-
- return name
-
-
- def add_queue(self, name = None, mode='thread', update:bool=False):
- if not hasattr(self, 'queue'):
- self.queue = self.munch({})
-
- name = self.resolve_queue_name(name)
- if name in self.queue and not update:
- return self.queue[name]
-
-
- if mode == 'thread':
- self.queue[name] = queue.Queue()
- else:
- raise NotImplemented(mode)
-
- def add_queues(self, *names, **kwargs):
- for name in names:
- self.add_queue(name, **kwargs)
-
- def resolve_worker_name(self, name = None):
- if name is None:
- name = f'W::{len(self.workers)}'
- else:
- name = str(name)
- assert isinstance(name, str)
- assert name not in self.workers
- return name
-
- def add_workers(self, *names, **kwargs):
- if len(names) == 0:
- names = [self.resolve_worker_name(i) for i in range(self.config.num_workers)]
- for name in names:
- self.add_worker(name, **kwargs)
-
-
-
- @property
- def workers(self):
- return self.config.get('workers', {})
- @workers.setter
- def workers(self, value):
- self.config['workers'] = value
- return value
-
- @property
- def mode(self):
- return self.config.get('mode', {})
- @workers.setter
- def mode(self, value):
- self.config['mode'] = value
- return value
-
-
- def resolve_mode(self, mode = None):
- if mode is None:
- mode = self.config.mode
- return mode
-
- def add_worker(self, name = None,
- update:bool= False,
- fn = None,
- mode:str=None,
- in_queue:str=None,
- out_queue:str=None,
- verbose: bool = True):
- name = self.resolve_worker_name(name)
- mode = self.resolve_mode(mode)
-
-
- if name in self.workers and not update:
- return self.workers[name]
-
- queue_prefix = '::'.join(name.split('::')[:-1])
- kwargs = dict(
- in_queue = 'input' if in_queue is None else in_queue,
- out_queue = 'output' if out_queue is None else out_queue,
- fn = self.fn if fn is None else fn,
- )
-
- self.add_queue(kwargs['in_queue'], mode=mode)
- self.add_queue(kwargs['out_queue'], mode=mode)
-
- if verbose:
- self.print(f"Adding worker: {name}, mode: {mode}, kwargs: {kwargs}")
-
- self.lock = threading.Lock()
- if self.config.mode == 'thread':
-
- t = threading.Thread(target=self.forward_requests, kwargs=kwargs)
- worker = t
- self.workers[name] = t
- t.daemon = self.config.daemon
- t.start()
- elif self.config.mode == 'process':
- p = multiprocessing.Process(target=self.forward_requests, kwargs=kwargs)
- self.workers[name] = t
- p.start()
-
- else:
- raise ValueError("Invalid mode. Must be 'thread' or 'process'.")
-
- # write tests
- @classmethod
- def test(cls, **kwargs):
- self = cls(**kwargs)
- for i in range(10):
- self.put(dict(module='dataset.bittensor', fn='sample'))
- cls.print('Done')
- for i in range(10):
- self.get()
- # self.kill()
-
-
- def default_fn(self,request, **kwargs):
-
- if isinstance(request, dict):
- # get request from queue
- # get function and arguments
- module = request.get('module') # identity function
- fn = request.get('fn', 'forward') # identity function
- kwargs = request.get('kwargs', {})
- args = request.get('args', [])
- result = asyncio.run(c.call(module=module, fn=fn, *args,**kwargs))
- assert callable(fn), f"Invalid function: {fn}"
- output = fn(*args, **kwargs)
-
- return output
- else:
- return request
-
- def forward_requests(self, **kwargs):
-
- with self.lock:
- verbose = kwargs.get('verbose', True)
- in_queue = kwargs.get('in_queue', 'input')
- out_queue = kwargs.get('out_queue', 'output')
- fn = kwargs.get('fn', self.fn)
- name = kwargs.get('name', 'worker')
- worker_prefix = f"Worker::{name}"
-
- asyncio.set_event_loop(asyncio.new_event_loop())
- color= 'yellow'
- while True:
- request = self.queue[in_queue].get()
- if verbose:
- self.print(f"{worker_prefix} <-- request: {request}", color='yellow')
-
- if request == 'kill':
- if verbose:
- self.print(f"Killing worker: {name}", color='red')
- break
-
- try:
- output = fn(request, **kwargs)
- except Exception as e:
- output = str(e)
- self.print(f"Error: {e}", color='red')
- continue
- self.queue[out_queue].put(output)
-
- if verbose:
- self.print(f"{worker_prefix} --> result: {output}", color='green')
- def kill_loop(self):
- self.run_loop = False
-
- def kill_workers(self):
- # kill all workers
- for name, worker in self.workers.items():
- self.add_request('kill')
-
- def __del__(self):
- self.kill_workers()
- def put(self, request):
-
- self.queue.input.put(request)
-
- def get(self):
- return getattr(self.queue, q).get()
-
-
-if __name__ == "__main__":
- Pool.test()
- # Wait for all requests to be processed
- # queue.request_queue.join()
-
diff --git a/commune/modules/archive/storage/storage.py b/commune/modules/archive/storage/storage.py
deleted file mode 100644
index 38b5cf25f..000000000
--- a/commune/modules/archive/storage/storage.py
+++ /dev/null
@@ -1,141 +0,0 @@
-
-import commune
-from typing import *
-import streamlit as st
-class Storage(commune.Module):
-
- def __init__(self, store: Dict = None, key: 'Key' = None):
-
- self.set_storage(store)
- self.set_key(key)
-
-
- def set_storage(self, storage: Dict = None):
- storage = {} if storage == None else storage
- assert isinstance(storage, dict), 'storage must be a dictionary'
- self.storage = storage
-
-
- def put(self,
- k:str,
- v: Any,
- key: str = None,
- encrypt: bool = False) -> str:
- data = None
- key = self.resolve_key(key)
- if isinstance(v, dict):
- if 'data' in v and 'time' in v:
- data = v
-
- if data == None:
- data = {'data': v, 'time': int(commune.time())}
- if encrypt:
- data = key.encrypt(data)
- # start with signature, data, public_address
- storage_item = key.sign(data, return_dict=True)
- storage_item['encrypt'] = encrypt
-
- self.storage[k] = storage_item
-
-
- st.write(self.storage[k])
-
- return k
-
- def state_dict(self):
- import json
- state_dict = {}
- for k, v in self.storage.items():
- try:
- state_dict[k] = json.dumps(v)
- except:
- commune.log(f'could not serialize {k}')
-
- return state_dict
- def from_state_dict(self, state_dict: Dict) -> None:
- import json
- for k, v in state_dict.items():
- self.storage[k] = json.loads(v)
-
- def save(self, path: str):
-
- state_dict = self.state_dict()
-
- return self.put_json( path=path, data=state_dict)
-
-
- def resolve_key(self, key: str = None) -> commune.key:
- if key == None:
- key = self.key
- return key
-
- def get(self,
- k,
- key:str = None,
- max_staleness: int = 1000) -> Any:
- key = self.resolve_key(key)
-
- item = self.storage[k]
- verified = key.verify(item)
-
- # decrypt if necessary
- if self.is_encrypted(item):
-
- item['data'] = key.decrypt(item['data'])
- item['data'] = self.str2python(item['data'])
- assert verified, 'could not verify signature'
-
- # check staleness
- staleness = commune.time() - item['data']['time']
- assert staleness < max_staleness
-
- return item['data']['data']
-
-
- @property
- def key2address(self) -> Dict:
- key2address = {}
- for k, v in self.storage.items():
- id = v['ss58_address']
- if id in key2address:
- key2address[v['ss58_address']] += [k]
- else:
- key2address[v['ss58_address']] = [k]
-
- return key2address
-
-
- def is_encrypted(self, item: Dict) -> bool:
- return item.get('encrypt', False)
-
- @classmethod
- def test(cls):
- self = cls()
-
- object_list = [0, {'fam': 1}, 'whadup']
- for obj in object_list:
- self.put('test', obj)
- assert self.get('test') == obj
-
-
- @classmethod
- def sandbox(cls):
-
- self = cls()
- data = {'fam': 1, 'bro': 'fam', 'chris': {'sup': [1,'dawg']}}
- key = commune.key('Alice')
- st.write(self.put('bro',
- data,
- encrypt=False,
- key=key
- ))
- st.write(self.put('fam', data, key=commune.key('Bob'), encrypt=False))
-
- # st.write(self.get('bro'))
- st.write(self.key2address)
- st.write(self.state_dict())
-
-if __name__ == "__main__":
- Storage.sandbox()
-
-
\ No newline at end of file
diff --git a/commune/modules/archive/subprocess/subprocess_module.py b/commune/modules/archive/subprocess/subprocess_module.py
deleted file mode 100644
index a2b8c3f04..000000000
--- a/commune/modules/archive/subprocess/subprocess_module.py
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-import os, sys
-from commune import Module
-from commune.utils import *
-import shlex
-import subprocess
-
-class SubprocessModule(Module):
- subprocess_map = {}
- def __init__(self, config=None, **kwargs):
- Module.__init__(self, config=config)
- self.subprocess_map_path = self.cache_path
-
- def __reduce__(self):
- deserializer = self.__class__
- serialized_data = (self.config,)
- return deserializer, serialized_data
-
- def submit(command):
- return self.run_command(command)
-
- @property
- def subprocess_map(self):
- self.load_cache()
- return self.cache
-
- def rm_subprocess(self, key):
- subprocess_dict = self.subprocess_map[key]
- pid = subprocess_dict['pid']
- try:
- self.kill_pid(pid)
- except ProcessLookupError:
- pass
- self.pop_cache(key)
-
- return pid
-
- rm = rm_subprocess
-
- def rm_all(self):
- rm_dict = {}
- for k in self.list_keys():
- rm_dict[k] = self.rm(key=k, load=False, save=False)
-
- return rm_dict
-
- def add_subprocess(self, command:str,key=None, cache=True, add_info={}):
-
- process = subprocess.Popen(shlex.split(command))
- process_state_dict = process.__dict__
- # process_state_dict.pop('_waitpid_lock')
-
- subprocess_dict = {k:v for k,v in process_state_dict.items() if k != '_waitpid_lock'}
- if cache == True:
- if key == None or key == 'pid':
- key= str(process.pid)
- subprocess_dict = dict_override(subprocess_dict, add_info)
- self.put_cache(key, subprocess_dict)
-
- return subprocess_dict
-
- submit = add = add_subprocess
-
- def ls(self):
- self.load_state()
- return list(self.subprocess_map.keys())
-
- ls_keys = list_keys = list = ls
-
-
- @property
- def portConnection( port : int, host='0.0.0.0'):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- result = s.connect_ex((host, port))
- if result == 0: return True
- return False
-
- @classmethod
- def streamlit(cls):
- st.write(cls().subprocess_map)
-
-if __name__ == "__main__":
- SubprocessModule.run()
- # import stre=amlit as st
- # module = SubprocessModule.deploy(actor=False, override={'refresh':True})
- # st.write(module)
- # import ray
-
- # # st.write(module.subprocess_map)
-
- # module.client.rest
-
-
- # st.write(ray.get(module.ls.remote()))
- # st.write(ray.get(module.rm_all.remote()))
- # st.write(module.add(key='pid', command='python commune/gradio/api/module.py --module="gradio.client.module.ClientModule"'))
- # st.write(module.getattr('cache'))
- # st.write(ray.get(module.ls.remote()))
-
-
-
diff --git a/commune/modules/archive/tokenizer/tokenizer.py b/commune/modules/archive/tokenizer/tokenizer.py
deleted file mode 100644
index d4a1215aa..000000000
--- a/commune/modules/archive/tokenizer/tokenizer.py
+++ /dev/null
@@ -1,142 +0,0 @@
-
-import commune
-import torch
-from typing import Dict, Any, List, Tuple
-import streamlit as st
-commune.new_event_loop()
-from commune.utils.tokenizer import get_translation_map, translate_logits_to_probs_std, \
- translate_special_token_text, pad_offsets, topk_token_phrases, compact_topk_token_phrases, \
- encode_topk, decode_topk, prep_tokenizer, check_tokenizer_equivalence
-
-shortcuts = {
- # 0-1B models
- 'gpt125m': 'EleutherAI/gpt-neo-125m',
-
- # 1-3B models
- 'gpt2.7b': 'EleutherAI/gpt-neo-2.7B',
- 'gpt3b': 'EleutherAI/gpt-neo-2.7B',
- 'opt1.3b': 'facebook/opt-1.3b',
- 'opt2.7b': 'facebook/opt-2.7b',
-
- # 0-7B models
- 'gptjt': 'togethercomputer/GPT-JT-6B-v1',
- 'gptjt_mod': 'togethercomputer/GPT-JT-Moderation-6B',
- 'gptj': 'EleutherAI/gpt-j-6b',
- 'gptj.pyg6b': 'PygmalionAI/pygmalion-6b',
- 'gpt6b': 'cerebras/Cerebras-GPT-6.7B',
- 'gptj.instruct': 'nlpcloud/instruct-gpt-j-fp16',
- 'gptj.codegen': 'moyix/codegen-2B-mono-gptj',
- 'gptj.hivemind': 'hivemind/gpt-j-6B-8bit',
- 'gptj.adventure': 'KoboldAI/GPT-J-6B-Adventure',
- 'gptj.pygppo': 'TehVenom/GPT-J-Pyg_PPO-6B',
- 'gptj.alpaca.gpt4': 'vicgalle/gpt-j-6B-alpaca-gpt4',
- 'gptj.alpaca': 'bertin-project/bertin-gpt-j-6B-alpaca',
- 'oa.galactia.6.7b': 'OpenAssistant/galactica-6.7b-finetuned',
- 'opt6.7b': 'facebook/opt-6.7b',
- 'llama': 'decapoda-research/llama-7b-hf',
- 'vicuna.13b': 'lmsys/vicuna-13b-delta-v0',
- 'vicuna.7b': 'lmsys/vicuna-7b-delta-v0',
- 'llama-trl': 'trl-lib/llama-7b-se-rl-peft',
- 'opt.nerybus': 'KoboldAI/OPT-6.7B-Nerybus-Mix',
-
- # # > 7B models
- 'oa.pythia.12b': 'OpenAssistant/oasst-sft-1-pythia-12b',
- 'gptneox': 'EleutherAI/gpt-neox-20b',
- 'gpt20b': 'EleutherAI/gpt-neox-20b',
- 'opt13b': 'facebook/opt-13b',
- 'gpt13b': 'cerebras/Cerebras-GPT-13B'
-
- }
-
-
-class Tokenizer(commune.Module):
- shortcuts = shortcuts
- def __init__(self, **kwargs):
-
- config = self.set_config(kwargs=kwargs)
- self.set_tokenizer(config)
-
-
- @property
- def device(self):
- return self.config['device']
- def set_tokenizer(self, config):
- from transformers import AutoTokenizer, AutoModel
- from commune.utils.tokenizer import prep_tokenizer
-
- tokenizer = config['tokenizer']
-
- try:
- # HACK TO INCLUDE LLAMA TOKENIZER
- tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast= True)
- except ValueError:
-
- print('resorting ot use_fast = False')
- tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast=False)
-
-
- self.tokenizer = tokenizer
-
- self.std_tokenizer = AutoTokenizer.from_pretrained(config['std_tokenizer'], use_fast= True)
- self.std_tokenizer = prep_tokenizer(self.std_tokenizer)
- self.tokenizer = prep_tokenizer(self.tokenizer, self.std_tokenizer)
- self.token_translator = self.get_module('model.token_translator')(tokenizer=tokenizer, std_tokenizer=self.std_tokenizer)
-
- return self.tokenizer
-
-
- def resolve_device(self, device):
- if device == None:
- device = self.device
- return device
- def tokenize(self, text: str = 'Whadup',
- padding=True,
- truncation=True,
- max_length=64,
- return_tensors='pt',
- add_special_tokens=False,
- device:str = None,
- **kwargs) -> torch.Tensor:
- """ Returns tokenized text as torch tensor. """
-
- sample = self.tokenizer(text,
- padding=padding,
- truncation=truncation,
- max_length=max_length,
- return_tensors=return_tensors,
- add_special_tokens=add_special_tokens,
- **kwargs) # assume tokenizer.padding_side = 'left'
-
- device = self.resolve_device(device)
-
- sample = dict(
- input_ids= sample['input_ids'].to(device),
- attention_mask= sample['attention_mask'].to(device)
- )
-
- return sample
-
-
-
- def detokenize(self, input_ids: torch.Tensor, **kwargs) -> torch.Tensor:
- """ Returns tokenized text as torch tensor. """
-
- text = self.tokenizer.batch_decode(input_ids,**kwargs) # assume tokenizer.padding_side = 'left'
-
- return text
-
-
- @classmethod
- def test(cls,**kwargs):
- text = 'Whadup'
- self = cls(**kwargs)
- print(self.tokenize(text))
- print(self.detokenize(self.tokenize(text)['input_ids']))
-
- @classmethod
- def deploy(cls, tokenizer):
- return cls.deploy(tag=tokenizer, kwargs=dict(tokenizer=tokenizer) )
-
-if __name__ == "__main__":
- Tokenizer.run()
-
\ No newline at end of file
diff --git a/commune/modules/archive/ws/client.py b/commune/modules/archive/ws/client.py
deleted file mode 100644
index a985337b9..000000000
--- a/commune/modules/archive/ws/client.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import asyncio
-import websockets
-import commune as c
-
-class WSClient(c.Module):
-
-
- def __init__(self,
- module = None,
- ip = '0.0.0.0',
- port:int=None,
- verbose:bool = False,
- key = None,
- start:bool = True):
- if ':' in ip:
- ip, port = ip.split(':')
- self.ip = c.resolve_ip(ip)
- self.port = c.resolve_port(port)
- self.address = f'ws://{self.ip}:{self.port}'
- self.verbose = verbose
- self.key = c.get_key(key)
- self.serializer = c.module('serializer')()
-
- def resolve_address(cls, address=None):
- if address == None:
- address = self.address
- if not 'ws://' in address:
- address = f'ws://{address}'
- assert isinstance(address, str), f'address must be a string, not {type(address)}'
- return address
-
- async def async_forward(self, fn='info', args=None, kwargs=None, address=None):
-
- if args == None:
- args = []
- if kwargs == None:
- kwargs = {}
-
- data = {'fn':fn, 'args':args, 'kwargs':kwargs}
- data = self.serializer.serialize(data)
- address = self.resolve_address(address=address)
- response = ''
- async with websockets.connect(address) as websocket:
- await websocket.send(data)
-
- while True:
- new_element = await websocket.recv()
- if new_element == '':
- break
- response += new_element
-
- c.print(response)
- response = self.serializer.deserialize(response)
-
-
- return response
-
- def forward(self, *args, **kwargs):
- return asyncio.get_event_loop().run_until_complete(self.async_forward(*args, **kwargs))
-
- @staticmethod
- async def recv(address):
- chunks = []
- async with websockets.connect(address) as websocket:
- chunk = await websocket.recv(address)
- chunks.append(chunk)
diff --git a/commune/modules/archive/ws/filetransfer.py b/commune/modules/archive/ws/filetransfer.py
deleted file mode 100644
index ab2b68634..000000000
--- a/commune/modules/archive/ws/filetransfer.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import asyncio
-import websockets
-import commune as c
-
-class FileTransfer(c.Module):
-
-
- def __init__(self,
- port:int=None,
- buffer_size:int=-1
- )
-
- self.set_server(port=port)
- self.set_queue(buffer_size=buffer_size)
-
- @staticmethod
- async def send_file(filename, address):
- async with websockets.connect(address) as websocket:
- with open(filename, 'rb') as file:
- while True:
- chunk = file.read(1024)
- if not chunk:
- break
- await websocket.send(chunk)
- await websocket.send('END')
-
- @staticmethod
- async def receive_file(address):
- async with websockets.connect(address) as websocket:
- with open('received_file.txt', 'wb') as file:
- while True:
- chunk = await websocket.recv()
- if chunk == 'END':
- break
- file.write(chunk)
-
- async def forward(websocket, path='file_to_send.txt'):
- with open(path, 'rb') as file:
- while True:
- chunk = file.read(1024)
- if not chunk:
- break
- await websocket.send(chunk)
- await websocket.send('END')
-
- def set_queue(self, buffer_size:int):
- import queue
- self.queue = queue.Queue(buffer_size)
-
-
- def set_server(self,port):
- port = self.resolve_port(port)
- start_server = websockets.serve(self.forward, 'localhost', port)
- asyncio.get_event_loop().run_until_complete(start_server)
- asyncio.get_event_loop().run_forever()
-
-
-
-if __name__ == "__main__":
- FileTransfer.run()
diff --git a/commune/modules/archive/ws/ws.py b/commune/modules/archive/ws/ws.py
deleted file mode 100644
index d0f40021a..000000000
--- a/commune/modules/archive/ws/ws.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import asyncio
-import websockets
-import commune as c
-
-class WS(c.Module):
-
-
- def __init__(self,
- ip = '0.0.0.0',
- port:int=None,
- queue_size:int=-1,
- verbose:bool = True,
- module = None):
- self.serializer = c.module('serializer')()
-
- if module == None:
- self.module = c.module(module)()
- self.set_server(ip=ip, port=port, queue_size=queue_size, verbose=verbose)
-
-
-
- def set_server(self, ip = '0.0.0.0', port = None, queue_size = -1, verbose = False):
- self.ip = c.resolve_ip(ip)
- self.port = c.resolve_port(port)
- self.queue = c.queue(queue_size)
- self.address = f'ws://{self.ip}:{self.port}'
- self.server = websockets.serve(self.forward, self.ip, self.port)
- c.print(f'Starting Server on {self.ip}:{self.port}')
- asyncio.get_event_loop().run_until_complete(self.server)
- asyncio.get_event_loop().run_forever()
-
-
- def put(self, chunk):
- return self.queue.put(chunk)
-
- async def forward(self, websocket):
- c.print(f'Starting Server Forwarding from {self.ip}:{self.port}')
-
- async for m in websocket:
- m = self.serializer.deserialize(m)
-
-
- m = self.serializer.serialize(m)
- await websocket.send(m)
-
- await websocket.send('')
-
-
- def __del__(self):
- c.deregister_server(self.name)
-
-
-
diff --git a/commune/modules/base/base.py b/commune/modules/base/base.py
deleted file mode 100644
index 00a274e85..000000000
--- a/commune/modules/base/base.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import commune as c
-
-class Demo(c.Module):
- def __init__(self, config = None, **kwargs):
- self.set_config(config, kwargs=kwargs)
-
- def call(self, x:int = 1, y:int = 2) -> int:
- c.print(self.config.sup)
- c.print(self.config, 'This is the config, it is a Munch object')
- return x + y
-
\ No newline at end of file
diff --git a/commune/modules/bittensor/Readme.md b/commune/modules/bittensor/Readme.md
deleted file mode 100644
index b094a5e70..000000000
--- a/commune/modules/bittensor/Readme.md
+++ /dev/null
@@ -1,26 +0,0 @@
-## Bittensor
-
-
-Bittensor works on a coldkey and hotkey abstraction. We have a wallet abstraction called {coldkey}.{hotkey}
-```python
-
-wallet = f"{coldkey}.{hotkey}"
-
-module = commune.get_commune('bittensor')
-moduel(wallet=wallet).register(dev_ids = [0,1,2])
-
-```
-
-1. Enter commune
-
- ```bash
- make enter;
- #or
- source env/bin/activate;
- ```
-
-2. Run registration
- ```
- python3
-
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/__init__.py b/commune/modules/bittensor/__init__.py
deleted file mode 100644
index 8b0d22cc1..000000000
--- a/commune/modules/bittensor/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# from .subtensor import subtensor
\ No newline at end of file
diff --git a/commune/modules/bittensor/axon/__init__.py b/commune/modules/bittensor/axon/__init__.py
deleted file mode 100644
index df8fab339..000000000
--- a/commune/modules/bittensor/axon/__init__.py
+++ /dev/null
@@ -1,500 +0,0 @@
-""" Create and init Axon, whcih services Forward and Backward requests from other neurons.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2022 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import os
-import copy
-import inspect
-import time
-from concurrent import futures
-from typing import Dict, List, Callable, Optional, Tuple, Union
-from bittensor._threadpool import prioritythreadpool
-
-import torch
-import grpc
-from substrateinterface import Keypair
-
-import bittensor
-from . import axon_impl
-
-class axon:
- """ The factory class for bittensor.Axon object
- The Axon is a grpc server for the bittensor network which opens up communication between it and other neurons.
- The server protocol is defined in bittensor.proto and describes the manner in which forward and backwards requests
- are transported / encoded between validators and servers
-
- Examples::
- >>> config = bittensor.axon.config()
- >>> axon = bittensor.axon( config = config )
- >>> subtensor = bittensor.subtensor( network = 'nakamoto' )
- >>> axon.serve( subtensor = subtensor )
- """
-
- def __new__(
- cls,
- netuid: int,
- config: Optional['bittensor.config'] = None,
- wallet: Optional['bittensor.Wallet'] = None,
- forward_text: Optional['Callable'] = None,
- backward_text:Optional['Callable'] = None,
- synapse_last_hidden: Optional['Callable'] = None,
- synapse_causal_lm: Optional['Callable'] = None,
- synapse_causal_lm_next: Optional['Callable'] = None,
- synapse_seq_2_seq: Optional['Callable'] = None,
- synapse_lasthidden_timeout: Optional[int] = None,
- synapse_causallm_timeout: Optional[int] = None,
- synapse_causallmnext_timeout: Optional[int] = None,
- synapse_seq2seq_timeout: Optional[int] = None,
-
- synapse_checks: Optional['Callable'] = None,
- thread_pool: Optional['futures.ThreadPoolExecutor'] = None,
- priority_threadpool: Optional['bittensor.prioritythreadpool'] = None,
- server: Optional['grpc._Server'] = None,
- port: Optional[int] = None,
- ip: Optional[str] = None,
- external_ip: Optional[str] = None,
- external_port: Optional[int] = None,
- protocol: Optional[int] = None,
- max_workers: Optional[int] = None,
- maximum_concurrent_rpcs: Optional[int] = None,
- blacklist: Optional['Callable'] = None,
- priority: Optional['Callable'] = None,
- forward_timeout: Optional[int] = None,
- backward_timeout: Optional[int] = None,
- compression:Optional[str] = None,
- ) -> 'bittensor.Axon':
- r""" Creates a new bittensor.Axon object from passed arguments.
- Args:
- netuid (:obj:`int`, `required`):
- The netuid of the subent this axon is serving on.
- config (:obj:`Optional[bittensor.Config]`, `optional`):
- bittensor.axon.config()
- wallet (:obj:`Optional[bittensor.Wallet]`, `optional`):
- bittensor wallet with hotkey and coldkeypub.
- forward_text (:obj:`Optional[callable]`, `optional`):
- function which is called on forward text requests.
- backward_text (:obj:`Optional[callable]`, `optional`):
- function which is called on backward text requests.
- synapse_last_hidden (:obj:`Optional[callable]`, `optional`):
- function which is called by the last hidden synapse
- synapse_causal_lm (:obj:`Optional[callable]`, `optional`):
- function which is called by the causal lm synapse
- synapse_causal_lm_next (:obj:`Optional[callable]`, `optional`):
- function which is called by the TextCausalLMNext synapse
- synapse_seq_2_seq (:obj:`Optional[callable]`, `optional`):
- function which is called by the seq2seq synapse
- synapse_checks (:obj:`Optional[callable]`, 'optional'):
- function which is called before each synapse to check for stake
- thread_pool (:obj:`Optional[ThreadPoolExecutor]`, `optional`):
- Threadpool used for processing server queries.
- server (:obj:`Optional[grpc._Server]`, `required`):
- Grpc server endpoint, overrides passed threadpool.
- port (:type:`Optional[int]`, `optional`):
- Binding port.
- ip (:type:`Optional[str]`, `optional`):
- Binding ip.
- external_ip (:type:`Optional[str]`, `optional`):
- The external ip of the server to broadcast to the network.
- external_port (:type:`Optional[int]`, `optional`):
- The external port of the server to broadcast to the network.
- protocol (:type:`Optional[int]`, `optional`):
- The protocol of the server to broadcast to the network.
- max_workers (:type:`Optional[int]`, `optional`):
- Used to create the threadpool if not passed, specifies the number of active threads servicing requests.
- maximum_concurrent_rpcs (:type:`Optional[int]`, `optional`):
- Maximum allowed concurrently processed RPCs.
- blacklist (:obj:`Optional[callable]`, `optional`):
- function to blacklist requests.
- priority (:obj:`Optional[callable]`, `optional`):
- function to assign priority on requests.
- forward_timeout (:type:`Optional[int]`, `optional`):
- timeout on the forward requests.
- backward_timeout (:type:`Optional[int]`, `optional`):
- timeout on the backward requests.
- """
- if config == None:
- config = axon.config()
- config = copy.deepcopy(config)
- config.axon.port = port if port != None else config.axon.port
- config.axon.ip = ip if ip != None else config.axon.ip
- config.axon.external_ip = external_ip if external_ip != None else config.axon.external_ip
- config.axon.external_port = external_port if external_port != None else config.axon.external_port
- config.axon.protocol = protocol if protocol != None else config.axon.protocol
- config.axon.max_workers = max_workers if max_workers != None else config.axon.max_workers
- config.axon.maximum_concurrent_rpcs = maximum_concurrent_rpcs if maximum_concurrent_rpcs != None else config.axon.maximum_concurrent_rpcs
- config.axon.forward_timeout = forward_timeout if forward_timeout != None else config.axon.forward_timeout
- config.axon.backward_timeout = backward_timeout if backward_timeout != None else config.axon.backward_timeout
- config.axon.compression = compression if compression != None else config.axon.compression
- config.axon.lasthidden_timeout = synapse_lasthidden_timeout if synapse_lasthidden_timeout != None else config.axon.lasthidden_timeout
- config.axon.causallm_timeout = synapse_causallm_timeout if synapse_causallm_timeout != None else config.axon.causallm_timeout
- config.axon.causallmnext_timeout = synapse_causallmnext_timeout if synapse_causallmnext_timeout is not None else config.axon.causallmnext_timeout
- config.axon.seq2seq_timeout = synapse_seq2seq_timeout if synapse_seq2seq_timeout != None else config.axon.seq2seq_timeout
- axon.check_config( config )
-
- # Determine the grpc compression algorithm
- if config.axon.compression == 'gzip':
- compress_alg = grpc.Compression.Gzip
- elif config.axon.compression == 'deflate':
- compress_alg = grpc.Compression.Deflate
- else:
- compress_alg = grpc.Compression.NoCompression
-
- if wallet == None:
- wallet = bittensor.wallet( config = config )
- if thread_pool == None:
- thread_pool = futures.ThreadPoolExecutor( max_workers = config.axon.max_workers )
- if server == None:
- receiver_hotkey = wallet.hotkey.ss58_address
- server = grpc.server( thread_pool,
- interceptors=(AuthInterceptor(receiver_hotkey=receiver_hotkey, blacklist=blacklist),),
- maximum_concurrent_rpcs = config.axon.maximum_concurrent_rpcs,
- options = [('grpc.keepalive_time_ms', 100000),
- ('grpc.keepalive_timeout_ms', 500000),
- ('grpc.max_receive_message_length', config.axon.maximum_message_length)
- ]
- )
-
- synapses = {}
- synapses[bittensor.proto.Synapse.SynapseType.TEXT_LAST_HIDDEN_STATE] = synapse_last_hidden
- synapses[bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM] = synapse_causal_lm
- synapses[bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM_NEXT] = synapse_causal_lm_next
- synapses[bittensor.proto.Synapse.SynapseType.TEXT_SEQ_2_SEQ] = synapse_seq_2_seq
-
- synapse_timeouts = {
- bittensor.proto.Synapse.SynapseType.TEXT_LAST_HIDDEN_STATE: config.axon.lasthidden_timeout,
- bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM: config.axon.causallm_timeout,
- bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM_NEXT: config.axon.causallmnext_timeout,
- bittensor.proto.Synapse.SynapseType.TEXT_SEQ_2_SEQ: config.axon.seq2seq_timeout
- }
-
- synapse_check_function = synapse_checks if synapse_checks != None else axon.default_synapse_check
-
- if priority != None and priority_threadpool == None:
- priority_threadpool = bittensor.prioritythreadpool(config=config)
-
- axon_instance = axon_impl.Axon(
- wallet = wallet,
- server = server,
- ip = config.axon.ip,
- port = config.axon.port,
- external_ip=config.axon.external_ip, # don't use internal ip if it is None, we will try to find it later
- external_port=config.axon.external_port or config.axon.port, # default to internal port if external port is not set
- protocol = config.axon.protocol,
- forward = forward_text,
- backward = backward_text,
- synapses = synapses,
- synapse_checks = synapse_check_function,
- synapse_timeouts = synapse_timeouts,
- priority = priority,
- priority_threadpool = priority_threadpool,
- forward_timeout = config.axon.forward_timeout,
- backward_timeout = config.axon.backward_timeout,
- prometheus_level = config.axon.prometheus.level,
- netuid = netuid,
- )
- bittensor.grpc.add_BittensorServicer_to_server( axon_instance, server )
- full_address = str( config.axon.ip ) + ":" + str( config.axon.port )
- server.add_insecure_port( full_address )
- return axon_instance
-
- @classmethod
- def config(cls) -> 'bittensor.Config':
- """ Get config from the argument parser
- Return: bittensor.config object
- """
- parser = argparse.ArgumentParser()
- axon.add_args( parser )
- return bittensor.config( parser )
-
- @classmethod
- def help(cls):
- """ Print help to stdout
- """
- parser = argparse.ArgumentParser()
- cls.add_args( parser )
- print (cls.__new__.__doc__)
- parser.print_help()
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser, prefix: str = None ):
- """ Accept specific arguments from parser
- """
- prefix_str = '' if prefix == None else prefix + '.'
- try:
- parser.add_argument('--' + prefix_str + 'axon.port', type=int,
- help='''The local port this axon endpoint is bound to. i.e. 8091''', default = bittensor.defaults.axon.port)
- parser.add_argument('--' + prefix_str + 'axon.ip', type=str,
- help='''The local ip this axon binds to. ie. [::]''', default = bittensor.defaults.axon.ip)
- parser.add_argument('--' + prefix_str + 'axon.external_port', type=int, required=False,
- help='''The public port this axon broadcasts to the network. i.e. 8091''', default = bittensor.defaults.axon.external_port)
- parser.add_argument('--' + prefix_str + 'axon.external_ip', type=str, required=False,
- help='''The external ip this axon broadcasts to the network to. ie. [::]''', default = bittensor.defaults.axon.external_ip)
- parser.add_argument('--' + prefix_str + 'axon.protocol', type=int, required=False,
- help='''The protocol this axon broadcasts to the network. i.e. 0''', default = bittensor.defaults.axon.protocol)
- parser.add_argument('--' + prefix_str + 'axon.max_workers', type=int,
- help='''The maximum number connection handler threads working simultaneously on this endpoint.
- The grpc server distributes new worker threads to service requests up to this number.''', default = bittensor.defaults.axon.max_workers)
- parser.add_argument('--' + prefix_str + 'axon.maximum_concurrent_rpcs', type=int,
- help='''Maximum number of allowed active connections''', default = bittensor.defaults.axon.maximum_concurrent_rpcs)
- parser.add_argument('--' + prefix_str + 'axon.backward_timeout', type=int,
- help='Number of seconds to wait for backward axon request', default=2*bittensor.__blocktime__)
- parser.add_argument('--' + prefix_str + 'axon.forward_timeout', type=int,
- help='Number of seconds to wait for forward axon request', default=5*bittensor.__blocktime__)
- parser.add_argument('--' + prefix_str + 'axon.priority.max_workers', type = int,
- help='''maximum number of threads in thread pool''', default = bittensor.defaults.axon.priority.max_workers)
- parser.add_argument('--' + prefix_str + 'axon.priority.maxsize', type=int,
- help='''maximum size of tasks in priority queue''', default = bittensor.defaults.axon.priority.maxsize)
- parser.add_argument('--' + prefix_str + 'axon.compression', type=str,
- help='''Which compression algorithm to use for compression (gzip, deflate, NoCompression) ''', default = bittensor.defaults.axon.compression)
- parser.add_argument('--' + prefix_str + 'axon.lasthidden_timeout', type = int,
- help='Timeout for last hidden synapse', default= bittensor.__blocktime__)
- parser.add_argument('--' + prefix_str + 'axon.causallm_timeout', type = int,
- help='Timeout for causallm synapse', default= bittensor.__blocktime__)
- parser.add_argument('--' + prefix_str + 'axon.causallmnext_timeout', type = int,
- help='Timeout for causallmnext synapse', default= bittensor.__blocktime__)
- parser.add_argument('--' + prefix_str + 'axon.seq2seq_timeout', type = int,
- help='Timeout for seq2seq synapse', default= 3*bittensor.__blocktime__)
- parser.add_argument('--' + prefix_str + 'axon.maximum_message_length', type = int,
- help='Maximum message length for requestion', default= 4*1024*1024)
- parser.add_argument('--' + prefix_str + 'axon.prometheus.level',
- required = False,
- type = str,
- choices = [l.name for l in list(bittensor.prometheus.level)],
- default = bittensor.defaults.axon.prometheus.level,
- help = '''Prometheus logging level axon. ''')
- except argparse.ArgumentError:
- # re-parsing arguments.
- pass
-
- bittensor.wallet.add_args( parser, prefix = prefix )
-
- @classmethod
- def add_defaults(cls, defaults):
- """ Adds parser defaults to object from enviroment variables.
- """
- defaults.axon = bittensor.Config()
- defaults.axon.port = os.getenv('BT_AXON_PORT') if os.getenv('BT_AXON_PORT') != None else 8091
- defaults.axon.ip = os.getenv('BT_AXON_IP') if os.getenv('BT_AXON_IP') != None else '[::]'
- defaults.axon.protocol = os.getenv('BT_AXON_PROTOCOL') if os.getenv('BT_AXON_PROTOCOL') != None else 0
- defaults.axon.external_port = os.getenv('BT_AXON_EXTERNAL_PORT') if os.getenv('BT_AXON_EXTERNAL_PORT') != None else None
- defaults.axon.external_ip = os.getenv('BT_AXON_EXTERNAL_IP') if os.getenv('BT_AXON_EXTERNAL_IP') != None else None
- defaults.axon.max_workers = os.getenv('BT_AXON_MAX_WORERS') if os.getenv('BT_AXON_MAX_WORERS') != None else 10
- defaults.axon.maximum_concurrent_rpcs = os.getenv('BT_AXON_MAXIMUM_CONCURRENT_RPCS') if os.getenv('BT_AXON_MAXIMUM_CONCURRENT_RPCS') != None else 400
-
- defaults.axon.priority = bittensor.Config()
- defaults.axon.priority.max_workers = os.getenv('BT_AXON_PRIORITY_MAX_WORKERS') if os.getenv('BT_AXON_PRIORITY_MAX_WORKERS') != None else 10
- defaults.axon.priority.maxsize = os.getenv('BT_AXON_PRIORITY_MAXSIZE') if os.getenv('BT_AXON_PRIORITY_MAXSIZE') != None else -1
-
- defaults.axon.compression = 'NoCompression'
-
- # Prometheus
- defaults.axon.prometheus = bittensor.config()
- defaults.axon.prometheus.level = os.getenv('BT_AXON_PROMETHEUS_LEVEL') if os.getenv('BT_AXON_PROMETHEUS_LEVEL') != None else bittensor.prometheus.level.DEBUG.name
-
- @classmethod
- def check_config(cls, config: 'bittensor.Config' ):
- """ Check config for axon port and wallet
- """
- assert config.axon.port > 1024 and config.axon.port < 65535, 'port must be in range [1024, 65535]'
- assert config.axon.external_port is None or (config.axon.external_port > 1024 and config.axon.external_port < 65535), 'external port must be in range [1024, 65535]'
- assert config.axon.prometheus.level in [l.name for l in list(bittensor.prometheus.level)], "axon.prometheus.level must be in: {}".format([l.name for l in list(bittensor.prometheus.level)])
- bittensor.wallet.check_config( config )
-
- @classmethod
- def default_synapse_check(cls, synapse, hotkey, inputs ):
- """ default synapse check function
- """
- if len(hotkey) == bittensor.__ss58_address_length__:
- return True
-
- return False
-
- @staticmethod
- def check_backward_callback( backward_callback:Callable, pubkey:str = '_' ):
- """ Check and test axon backward callback function
- """
- if not inspect.ismethod(backward_callback) and not inspect.isfunction(backward_callback):
- raise ValueError('The axon backward callback must be a function with signature Callable[inputs_x:torch.FloatTensor, grads_dy:torch.FloatTensor ) -> torch.FloatTensor:, got {}'.format(backward_callback))
- if len( inspect.signature(backward_callback).parameters) != 3:
- raise ValueError('The axon backward callback must have signature Callable[ inputs_x:torch.FloatTensor, grads_dy:torch.FloatTensor, synapses ) -> torch.FloatTensor:, got {}'.format(inspect.signature(backward_callback)))
- if 'inputs_x' not in inspect.signature(backward_callback).parameters:
- raise ValueError('The axon backward callback must have signature Callable[inputs_x:torch.FloatTensor, grads_dy:torch.FloatTensor ) -> torch.FloatTensor:, got {}'.format(inspect.signature(backward_callback)))
- if 'grads_dy' not in inspect.signature(backward_callback).parameters:
- raise ValueError('The axon backward callback must have signature Callable[inputs_x:torch.FloatTensor, grads_dy:torch.FloatTensor ) -> torch.FloatTensor:, got {}'.format(inspect.signature(backward_callback)))
-
-
- @staticmethod
- def check_forward_callback( forward_callback:Callable, synapses:list = []):
- """ Check and test axon forward callback function
- """
- if not inspect.ismethod(forward_callback) and not inspect.isfunction(forward_callback):
- raise ValueError('The axon forward callback must be a function with signature Callable[inputs_x: torch.Tensor] -> torch.FloatTensor:, got {}'.format(forward_callback))
- if len( inspect.signature(forward_callback).parameters) != 3:
- raise ValueError('The axon forward callback must have signature Callable[ inputs_x: torch.Tensor, synapses, hotkey] -> torch.FloatTensor:, got {}'.format(inspect.signature(forward_callback)))
- if 'inputs_x' not in inspect.signature(forward_callback).parameters:
- raise ValueError('The axon forward callback must have signature Callable[ inputs_x: torch.Tensor] -> torch.FloatTensor:, got {}'.format(inspect.signature(forward_callback)))
-
- sample_input = torch.randint(0,1,(3, 3))
- forward_callback([sample_input], synapses, hotkey='')
-
-class AuthInterceptor(grpc.ServerInterceptor):
- """Creates a new server interceptor that authenticates incoming messages from passed arguments."""
-
- def __init__(
- self,
- receiver_hotkey: str,
- blacklist: Callable = None,
- ):
- r"""Creates a new server interceptor that authenticates incoming messages from passed arguments.
- Args:
- receiver_hotkey(str):
- the SS58 address of the hotkey which should be targeted by RPCs
- black_list (Function, `optional`):
- black list function that prevents certain pubkeys from sending messages
- """
- super().__init__()
- self.nonces = {}
- self.blacklist = blacklist
- self.receiver_hotkey = receiver_hotkey
-
- def parse_legacy_signature(
- self, signature: str
- ) -> Union[Tuple[int, str, str, str, int], None]:
- r"""Attempts to parse a signature using the legacy format, using `bitxx` as a separator"""
- parts = signature.split("bitxx")
- if len(parts) < 4:
- return None
- try:
- nonce = int(parts[0])
- parts = parts[1:]
- except ValueError:
- return None
- receptor_uuid, parts = parts[-1], parts[:-1]
- signature, parts = parts[-1], parts[:-1]
- sender_hotkey = "".join(parts)
- return (nonce, sender_hotkey, signature, receptor_uuid, 1)
-
- def parse_signature_v2(
- self, signature: str
- ) -> Union[Tuple[int, str, str, str, int], None]:
- r"""Attempts to parse a signature using the v2 format"""
- parts = signature.split(".")
- if len(parts) != 4:
- return None
- try:
- nonce = int(parts[0])
- except ValueError:
- return None
- sender_hotkey = parts[1]
- signature = parts[2]
- receptor_uuid = parts[3]
- return (nonce, sender_hotkey, signature, receptor_uuid, 2)
-
- def parse_signature(
- self, metadata: Dict[str, str]
- ) -> Tuple[int, str, str, str, int]:
- r"""Attempts to parse a signature from the metadata"""
- signature = metadata.get("bittensor-signature")
- version = metadata.get('bittensor-version')
- if signature is None:
- raise Exception("Request signature missing")
- if int(version) < 370:
- raise Exception("Incorrect Version")
-
- for parser in [self.parse_signature_v2, self.parse_legacy_signature]:
- parts = parser(signature)
- if parts is not None:
- return parts
- raise Exception("Unknown signature format")
-
- def check_signature(
- self,
- nonce: int,
- sender_hotkey: str,
- signature: str,
- receptor_uuid: str,
- format: int,
- ):
- r"""verification of signature in metadata. Uses the pubkey and nonce"""
- keypair = Keypair(ss58_address=sender_hotkey)
- # Build the expected message which was used to build the signature.
- if format == 2:
- message = f"{nonce}.{sender_hotkey}.{self.receiver_hotkey}.{receptor_uuid}"
- elif format == 1:
- message = f"{nonce}{sender_hotkey}{receptor_uuid}"
- else:
- raise Exception("Invalid signature version")
- # Build the key which uniquely identifies the endpoint that has signed
- # the message.
- endpoint_key = f"{sender_hotkey}:{receptor_uuid}"
-
- if endpoint_key in self.nonces.keys():
- previous_nonce = self.nonces[endpoint_key]
- # Nonces must be strictly monotonic over time.
- if nonce <= previous_nonce:
- raise Exception("Nonce is too small")
-
- if not keypair.verify(message, signature):
- raise Exception("Signature mismatch")
- self.nonces[endpoint_key] = nonce
-
- def black_list_checking(self, hotkey: str, method: str):
- r"""Tries to call to blacklist function in the miner and checks if it should blacklist the pubkey"""
- if self.blacklist == None:
- return
-
- request_type = {
- "/Bittensor/Forward": bittensor.proto.RequestType.FORWARD,
- "/Bittensor/Backward": bittensor.proto.RequestType.BACKWARD,
- }.get(method)
- if request_type is None:
- raise Exception("Unknown request type")
-
- if self.blacklist(hotkey, request_type):
- raise Exception("Request type is blacklisted")
-
- def intercept_service(self, continuation, handler_call_details):
- r"""Authentication between bittensor nodes. Intercepts messages and checks them"""
- method = handler_call_details.method
- metadata = dict(handler_call_details.invocation_metadata)
-
- try:
- (
- nonce,
- sender_hotkey,
- signature,
- receptor_uuid,
- signature_format,
- ) = self.parse_signature(metadata)
-
- # signature checking
- self.check_signature(
- nonce, sender_hotkey, signature, receptor_uuid, signature_format
- )
-
- # blacklist checking
- self.black_list_checking(sender_hotkey, method)
-
- return continuation(handler_call_details)
-
- except Exception as e:
- message = str(e)
- abort = lambda _, ctx: ctx.abort(grpc.StatusCode.UNAUTHENTICATED, message)
- return grpc.unary_unary_rpc_method_handler(abort)
diff --git a/commune/modules/bittensor/axon/axon_impl.py b/commune/modules/bittensor/axon/axon_impl.py
deleted file mode 100644
index 4489a7b51..000000000
--- a/commune/modules/bittensor/axon/axon_impl.py
+++ /dev/null
@@ -1,864 +0,0 @@
-""" Implementation of Axon, services Forward and Backward requests from other neurons.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2022 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import sys
-import time as clock
-from types import SimpleNamespace
-from typing import List, Tuple, Callable
-
-import torch
-import grpc
-import wandb
-import pandas
-import uuid
-from loguru import logger
-import torch.nn.functional as F
-import concurrent
-
-
-import bittensor
-import bittensor.utils.stats as stat_utils
-from datetime import datetime
-
-logger = logger.opt(colors=True)
-
-from prometheus_client import Counter, Histogram, Enum, CollectorRegistry
-PROM_axon_is_started = Enum('axon_is_started', 'is_started', states=['stopped', 'started'])
-PROM_total_forward = Counter('axon_total_forward', 'total_forward', ['wallet', 'identifier'])
-PROM_total_backward = Counter('axon_total_backward', 'total_backward', ['wallet', 'identifier'])
-PROM_forward_latency = Histogram('axon_forward_latency', 'forward_latency', ['wallet', 'identifier'], buckets=list(range(0,bittensor.__blocktime__,1)))
-PROM_backward_latency = Histogram('axon_backward_latency', 'backward_latency', ['wallet', 'identifier'], buckets=list(range(0,bittensor.__blocktime__,1)))
-PROM_forward_synapses = Counter('axon_forward_synapses', 'forward_synapses', ['wallet', 'identifier', "synapse"])
-PROM_backward_synapses = Counter('axon_backward_synapses', 'backward_synapses', ['wallet', 'identifier', "synapse"])
-PROM_forward_codes = Counter('axon_forward_codes', 'forward_codes', ['wallet', 'identifier', "code"])
-PROM_backward_codes = Counter('axon_backward_codes', 'backward_codes', ['wallet', 'identifier', "code"])
-PROM_forward_hotkeys = Counter('axon_forward_hotkeys', 'forward_hotkeys', ['wallet', 'identifier', "hotkey"])
-PROM_backward_hotkeys = Counter('axon_backward_hotkeys', 'backward_hotkeys', ['wallet', 'identifier', "hotkey"])
-PROM_forward_bytes = Counter('axon_forward_bytes', 'forward_bytes', ['wallet', 'identifier', "hotkey"])
-PROM_backward_bytes = Counter('axon_backward_bytes', 'backward_bytes', ['wallet', 'identifier', "hotkey"])
-
-class Axon( bittensor.grpc.BittensorServicer ):
- r""" Services Forward and Backward requests from other neurons.
- """
- def __init__(
- self,
- wallet: 'bittensor.wallet',
- ip: str,
- port: int,
- external_ip: str,
- external_port: int,
- protocol: int,
- server: 'grpc._Server',
- forward: 'Callable',
- backward: 'Callable',
- synapses: dict,
- synapse_checks: 'Callable',
- synapse_timeouts: dict,
- prometheus_level: str,
- netuid: int,
- priority: 'Callable' = None,
- priority_threadpool: 'bittensor.prioritythreadpool' = None,
- forward_timeout: int = None,
- backward_timeout: int = None,
- ):
- r""" Initializes a new Axon tensor processing endpoint.
-
- Args:
- config (:obj:`bittensor.Config`, `required`):
- bittensor.axon.config()
- wallet (:obj:`bittensor.wallet`, `required`):
- bittensor wallet with hotkey and coldkeypub.
- server (:obj:`grpc._Server`, `required`):
- Grpc server endpoint.
- forward (:obj:list of `callable`, `optional`):
- list of functions which is called on forward requests.
- backward (:obj:list of `callable`, `optional`):
- list of functions which is called on backward requests.
- prometheus_level (:obj:`str`, `required`):
- Prometheus logging level.
- netuid (:obj:`int`, `required`):
- network uid for this axon.
- priority (:obj:`callable`, `optional`):
- function to assign priority on requests.
- priority_threadpool (:obj:`bittensor.prioritythreadpool`, `optional`):
- bittensor priority_threadpool.
- """
- self.ip = ip
- self.port = port
- self.external_ip = external_ip
- self.external_port = external_port
- self.protocol = protocol
- self.wallet = wallet
- self.server = server
- self.forward_callback = forward if forward != None else self.default_forward_callback
- self.backward_callback = backward if backward != None else self.default_backward_callback
- self.forward_timeout = forward_timeout
- self.backward_timeout = backward_timeout
- self.synapse_callbacks = synapses
- self.synapse_checks = synapse_checks
- self.synapse_timeouts = synapse_timeouts
- self.prometheus_level = prometheus_level
- self.stats = self._init_stats()
- self.started = None
-
- # -- Priority
- self.priority = priority
- self.priority_threadpool = priority_threadpool
- self._prometheus_uuid = uuid.uuid1()
-
- self.netuid = netuid
-
- def __str__(self) -> str:
- return "Axon({}, {}, netuid:{}, {}, {})".format( self.ip, self.port, self.netuid, self.wallet.hotkey.ss58_address, "started" if self.started else "stopped")
-
- def __repr__(self) -> str:
- return self.__str__()
-
- def Forward(self, request: bittensor.proto.TensorMessage, context: grpc.ServicerContext) -> bittensor.proto.TensorMessage:
- r""" The function called by remote GRPC Forward requests from other neurons.
- Forward is equivalent to a 'forward' pass through a neural network.
- After checking request validity, this function passes the request to the nucleus for processing.
- See :obj:`bittensor.proto.ReturnCode` for all possible return codes.
-
- Args:
- request (:obj:`bittensor.proto`, `required`):
- Tensor request proto.
- context (:obj:`grpc.ServicerContext`, `required`):
- grpc server context.
-
- Returns:
- response (bittensor.proto.TensorMessage):
- proto response carring the nucleus forward output or None under failure.
- """
- forward_response_tensors, code, synapses = self._forward( request )
- response = bittensor.proto.TensorMessage(
- version = bittensor.__version_as_int__,
- hotkey = self.wallet.hotkey.ss58_address,
- return_code = code,
- tensors = forward_response_tensors if forward_response_tensors is not None else [],
- requires_grad = request.requires_grad,
- synapses = synapses,
- )
- return response
-
- def Backward( self, request: bittensor.proto.TensorMessage, context: grpc.ServicerContext ) -> bittensor.proto.TensorMessage:
- r""" The function called by remote GRPC Backward requests from other neurons.
- Backward is equivalent to a 'backward' gradient descent pass through a neural network.
- After checking request validity, passes the request to the nucleus for processing.
- See :obj:`bittensor.proto.ReturnCode` for all possible return codes.
-
- Args:
- request (:obj:`bittensor.proto`, `required`):
- Tensor request proto.
- context (:obj:`grpc.ServicerContext`, `required`):
- grpc server context.
-
- Returns:
- response (:obj:`bittensor.proto.TensorMessage`):
- proto response carring the nucleus backward output or None under failure.
- """
- backward_response_tensors, code, synapses = self._backward( request )
- response = bittensor.proto.TensorMessage(
- version = bittensor.__version_as_int__,
- hotkey = self.wallet.hotkey.ss58_address,
- return_code = code,
- tensors = backward_response_tensors,
- requires_grad = request.requires_grad,
- synapses = synapses
- )
- return response
-
- def _forward(self, request):
- r""" Performs validity checks on the grpc request before passing the tensors to the forward queue.
- Returns the outputs and synapses from the backend forward call.
-
- Args:
- request (:obj:`bittensor.proto`, `required`):
- Tensor request proto.
- Returns:
- response (:obj:`bittensor.proto.Tensor, `required`):
- serialized tensor response from the nucleus call or None.
- code (:obj:`bittensor.proto.ReturnCode`, `required`):
- Code from the call. This specifies if the overall function call was a success.
- This is separate from the synapse returns codes which relate to the individual synapse call.
- synapses (:obj:`List[ 'bittensor.proto.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Synapse wire protos with return codes from forward request.
- """
- # ===================================================================
- # ==== First deserialize synapse wire protos to instance objects ====
- # ===================================================================
- synapses: List['bittensor.Synapse'] = []
- for synapse_wire_proto in request.synapses:
- synapses.append( bittensor.synapse.deserialize( synapse_wire_proto ) )
-
-
- # ===================================
- # ==== Init params from synapses ====
- # ===================================
- # These items are filled through the call and the function returns
- # when all codes are non-success or the function finishes completely.
- synapse_messages = [ "Success" for _ in synapses ]
- synapse_codes = [ bittensor.proto.ReturnCode.Success for _ in synapses ]
- synapse_inputs = [ None for _ in synapses ]
- synapse_responses = [ synapse.empty() for synapse in synapses ] # We fill nones for non success.
- synapse_is_response = [ False for _ in synapses ]
- synapse_call_times = [ 0 for _ in synapses ]
- synapse_timeout = min( [self.synapse_timeouts[s.synapse_type] for s in synapses] + [bittensor.__blocktime__] )
- start_time = clock.time()
-
- # ==================================================================
- # ==== Function which returns true if all codes are non success ====
- # ==================================================================
- def check_if_should_return() -> bool:
- for code in synapse_codes:
- if code == bittensor.proto.ReturnCode.Success:
- return False
- return True
-
-
- # ==============================================================
- # ==== Function which prints all log statements per synapse ====
- # ==============================================================
- def finalize_codes_stats_and_logs( message = None):
- # === Prometheus
- if self.prometheus_level != bittensor.prometheus.level.OFF.name:
- PROM_total_forward.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid ).inc()
- PROM_forward_latency.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid ).observe( clock.time() - start_time )
- if self.prometheus_level == bittensor.prometheus.level.DEBUG.name:
- PROM_forward_hotkeys.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, hotkey = request.hotkey ).inc()
- PROM_forward_bytes.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, hotkey = request.hotkey ).inc( sys.getsizeof( request ) )
-
- for index, synapse in enumerate( synapses ):
- # === Prometheus
- if self.prometheus_level != bittensor.prometheus.level.OFF.name:
- PROM_forward_synapses.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, synapse = str(synapse) ).inc()
- PROM_forward_codes.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, code = str(synapse_codes[ index ]) ).inc()
-
- # === Logging
- request.synapses [ index ].return_code = synapse_codes[ index ] # Set synapse wire proto codes.
- request.synapses [ index ].message = synapse_messages[ index ] # Set synapse wire proto message
- if synapse_is_response [index]:
- self.update_stats_for_request(request,synapse_codes[ index ])
- bittensor.logging.rpc_log (
- axon = True,
- forward = True,
- is_response = synapse_is_response [index],
- code = synapse_codes[ index ],
- call_time = synapse_call_times[ index ],
- pubkey = request.hotkey,
- inputs = deserialized_forward_tensors [index].shape if deserialized_forward_tensors [index] != None else None ,
- outputs = None if synapse_responses[index] == None else list( synapse_responses[index].shape ),
- message = synapse_messages[ index ] if message == None else message,
- synapse = synapse.synapse_type
- )
-
- # ======================================
- # ==== Check Empty request ====
- # ======================================
- if len(request.tensors) == 0:
- code = bittensor.proto.ReturnCode.EmptyRequest
- message = "Forward request contains {} tensors, expected 1 tensor in the forward call".format(len(request.tensors))
- call_time = clock.time() - start_time
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], code, request.synapses
-
-
- # ======================================
- # ==== Check request length ====
- # ======================================
- if len( request.tensors ) != len( synapses ):
- # Not enough responses per request.
- code = bittensor.proto.ReturnCode.RequestShapeException
- call_time = clock.time() - start_time
- message = "Request length doesn't match synape length."
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], bittensor.proto.ReturnCode.RequestShapeException, request.synapses
-
-
- # ===================================
- # ==== Deserialize/Check inputs ====
- # ===================================
- deserialized_forward_tensors = [ None for _ in synapses]
- for index, synapse in enumerate( synapses ):
- try:
- deserialized_forward_tensors [index] = synapse.deserialize_forward_request_tensor ( request.tensors [index] )
-
- except ValueError as e:
- synapse_codes [index] = bittensor.proto.ReturnCode.RequestShapeException
- synapse_call_times [index] = clock.time() - start_time
- synapse_messages [index] = 'Input shape exception with error:{}'.format(str(e))
-
- except Exception as e:
- synapse_codes [index] = bittensor.proto.ReturnCode.RequestDeserializationException
- synapse_call_times [index] = clock.time() - start_time
- synapse_messages [index] = 'Input deserialization exception with error:{}'.format(str(e))
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_codes_stats_and_logs()
- return [], synapse_codes[0] , request.synapses
-
-
- # ===================================
- # ==== Make forward calls. =========
- # ===================================
- try:
- finalize_codes_stats_and_logs()
- if self.priority != None:
- priority = self.priority( request.hotkey, inputs_x = deserialized_forward_tensors, request_type = bittensor.proto.RequestType.FORWARD )
- future = self.priority_threadpool.submit (
- self.forward_callback,
- inputs_x = deserialized_forward_tensors,
- synapses = synapses,
- priority = priority,
- hotkey = request.hotkey
- )
- forward_response_tensors, forward_codes, forward_messages = future.result( timeout = synapse_timeout - (clock.time() - start_time) )
- else:
-
- forward_response_tensors, forward_codes, forward_messages = self.forward_callback(
- inputs_x = deserialized_forward_tensors,
- synapses = synapses,
- hotkey= request.hotkey
- )
- synapse_is_response = [ True for _ in synapses ]
- # ========================================
- # ==== Fill codes from forward calls ====
- # ========================================
- for index, synapse in enumerate(synapses):
- synapse_codes [ index ] = forward_codes [ index ]
- synapse_messages [index] = forward_messages [ index ]
- # ========================================
- # ==== Catch forward request timeouts ====
- # ========================================
- except concurrent.futures.TimeoutError:
- if self.priority != None:
- future.cancel()
- code = bittensor.proto.ReturnCode.Timeout
- call_time = clock.time() - start_time
- message = "Request reached timeout"
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], bittensor.proto.ReturnCode.Timeout, request.synapses
-
- # ==================================
- # ==== Catch unknown exceptions ====
- # ==================================
- except Exception as e:
- code = bittensor.proto.ReturnCode.UnknownException
- call_time = clock.time() - start_time
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ 'Exception on Server' for _ in synapses ]
- finalize_codes_stats_and_logs(message = str(e))
- return [], bittensor.proto.ReturnCode.UnknownException, request.synapses
-
- # =================================================
- # ==== Encode/serialize responses and synapses ====
- # ==================================================
- response_synapses = []
- for index, synapse in enumerate( synapses ):
- try:
- if synapse_codes[index] == bittensor.proto.ReturnCode.Success:
- synapse_responses [ index ] = synapse.serialize_forward_response_tensor( deserialized_forward_tensors[ index ], forward_response_tensors [ index ] )
- else:
- synapse_responses [ index ] = synapse.empty()
-
- except ValueError as e:
- if str(e) == 'Empty Response':
- synapse_codes [ index ]= bittensor.proto.ReturnCode.EmptyResponse
- else:
- synapse_codes [ index ]= bittensor.proto.ReturnCode.ResponseShapeException
-
- synapse_call_times [ index ] = clock.time() - start_time
- synapse_messages [index] = "Synapse response shape exception with error: {}".format( str( e ) )
- synapse_responses [ index ] = synapse.empty()
-
- except Exception as e:
- synapse_codes [ index ]= bittensor.proto.ReturnCode.ResponseSerializationException
- synapse_call_times [ index ] = clock.time() - start_time
- synapse_messages [index] = "Synapse response serialization exception with error: {}".format( str( e ) )
- synapse_responses [ index ] = synapse.empty()
-
- response_synapses.append(synapse.serialize_to_wire_proto(code = synapse_codes[index], message= synapse_messages[index] ))
-
-
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_codes_stats_and_logs()
- return [], synapse_codes[0], request.synapses
-
- # =========================================================
- # ==== Set return times for successfull forward ===========
- # =========================================================
- for index, _ in enumerate( synapses ):
- if synapse_codes[index] == bittensor.proto.ReturnCode.Success:
- synapse_call_times[index] = clock.time() - start_time
-
- finalize_codes_stats_and_logs()
- return synapse_responses, bittensor.proto.ReturnCode.Success, response_synapses
-
- def _backward(self, request):
- r""" Performs validity checks on the grpc request before piping the request to the backend queue.
- Returns the outputs and synapses (with codes and messages from the backward call.)
- Args:
- request (:obj:`bittensor.proto`, `required`):
- Tensor request proto.
- Returns:
- response: (:obj:`bittensor.proto.Tensor, `required`):
- serialized tensor gradient responses. This is always an empty vector until gradients are allowed.
- code (:obj:`bittensor.proto.ReturnCode`, `required`):
- Code from the call. This specifies if the overall function call was a success.
- This is separate from the synapse returns codes which relate to the individual synapse call.
- synapses (:obj:`List[ 'bittensor.proto.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Synapse wire protos with return codes from forward request.
- """
-
- # ===================================================================
- # ==== First deserialize synapse wire protos to instance objects ====
- # ===================================================================
- synapses: List['bittensor.Synapse'] = []
- for synapse_wire_proto in request.synapses:
- synapses.append( bittensor.synapse.deserialize( synapse_wire_proto ) )
-
- # ===================================
- # ==== Init params from synapses ====
- # ===================================
- # These items are filled through the call and the function returns
- # when all codes are non-success or the function finishes completely.
- synapse_messages = [ "Success" for _ in synapses ]
- synapse_codes = [ bittensor.proto.ReturnCode.Success for _ in synapses ]
- deserialized_forward_tensors = [ None for _ in synapses ]
- deserialized_forward_gradients = [ None for _ in synapses ]
- synapse_is_response = [ False for _ in synapses ]
- synapse_call_times = [ 0 for _ in synapses ]
- start_time = clock.time()
-
- # ==================================================================
- # ==== Function which returns true if all codes are non success ====
- # ==================================================================
- def check_if_should_return() -> bool:
- for code in synapse_codes:
- if code == bittensor.proto.ReturnCode.Success:
- return False
- return True
-
- # ==============================================================
- # ==== Function which prints all log statements per synapse ====
- # ==============================================================
- def finalize_codes_stats_and_logs():
- # === Prometheus
- if self.prometheus_level != bittensor.prometheus.level.OFF.name:
- PROM_total_backward.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid ).inc()
- PROM_backward_latency.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid ).observe( clock.time() - start_time )
- if self.prometheus_level == bittensor.prometheus.level.DEBUG.name:
- PROM_backward_hotkeys.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, hotkey = request.hotkey ).inc()
- PROM_backward_bytes.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, hotkey = request.hotkey ).inc( sys.getsizeof( request ) )
-
- for index, synapse in enumerate( synapses ):
- # === Prometheus
- if self.prometheus_level != bittensor.prometheus.level.OFF.name:
- PROM_backward_synapses.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, synapse = str(synapse) ).inc()
- PROM_backward_codes.labels( wallet = self.wallet.hotkey.ss58_address, identifier = self._prometheus_uuid, code = str(synapse_codes[ index ]) ).inc()
-
- # === Logging
- request.synapses [ index ].return_code = synapse_codes[ index ] # Set synapse wire proto codes.
- request.synapses [ index ].message = synapse_messages[ index ] # Set synapse wire proto message
-
- bittensor.logging.rpc_log (
- axon = True,
- forward = False,
- is_response = synapse_is_response [index],
- code = synapse_codes[ index ],
- call_time = synapse_call_times[ index ],
- pubkey = request.hotkey,
- inputs = None if deserialized_forward_gradients[index] == None else deserialized_forward_gradients[index].shape ,
- outputs = None, # we never return from backward.
- message = synapse_messages[ index ],
- synapse = synapse.synapse_type
- )
-
- # ======================================
- # ==== Check Empty request ====
- # ======================================
- if len(request.tensors) == 0:
- code = bittensor.proto.ReturnCode.EmptyRequest
- message = "Empty Request"
- call_time = clock.time() - start_time
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], code, request.synapses
-
- # ======================================
- # ==== Check Invalid request ====
- # ======================================
- if len(request.tensors) < 2:
- code = bittensor.proto.ReturnCode.InvalidRequest
- message = "Backward request contains {} tensors, expected atleast 2 tensor in the backward call".format(len(request.tensors))
- call_time = clock.time() - start_time
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], code, request.synapses
-
- # ======================================
- # ==== Check request length ====
- # ======================================
- if len( request.tensors ) != 2 * len( synapses ): # 2 per synapse (1 input + 1 grad).
- # Not enough responses per request.
- code = bittensor.proto.ReturnCode.RequestShapeException
- call_time = clock.time() - start_time
- message = "Request length doesn't match synape length."
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], code, request.synapses
-
- # ===================================
- # ==== Deserialize/Decode inputs ====
- # ===================================
- for index, synapse in enumerate( synapses ):
- try:
- deserialized_forward_tensors [index] = synapse.deserialize_forward_request_tensor ( request.tensors [index] )
- deserialized_forward_gradients [index] = synapse.deserialize_backward_request_gradient ( deserialized_forward_tensors [index], request.tensors [ len( synapses ) + index ] )
-
- except ValueError as e:
- synapse_codes [index] = bittensor.proto.ReturnCode.RequestShapeException
- synapse_call_times [index] = clock.time() - start_time
- synapse_messages [index] = 'Input shape exception with error:{}'.format(str(e))
-
- except Exception as e:
- synapse_codes [index] = bittensor.proto.ReturnCode.RequestDeserializationException
- synapse_call_times [index] = clock.time() - start_time
- synapse_messages [index] = 'Input deserialization exception with error:{}'.format(str(e))
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_codes_stats_and_logs()
- return [], synapse_codes[0], request.synapses
-
-
- # ===================================
- # ==== Make backward calls. =========
- # ===================================
- try:
- finalize_codes_stats_and_logs()
- synapse_is_response = [ True for _ in synapses ]
- if self.priority != None:
- # No wait on backward calls.
- priority = self.priority( request.hotkey, inputs_x = deserialized_forward_tensors, request_type = bittensor.proto.RequestType.BACKWARD )
- self.priority_threadpool.submit(
- self.backward_callback,
- inputs_x = deserialized_forward_tensors,
- grads_dy = deserialized_forward_gradients,
- synapses = synapses,
- priority = priority
- )
-
- else:
- # Calling default
- backward_response_tensors, backward_codes, backward_messages = self.backward_callback ( deserialized_forward_tensors, deserialized_forward_gradients, synapses = synapses )
-
- # ========================================
- # ==== Fill codes from forward calls ====
- # ========================================
- for index, synapse in enumerate(synapses):
- synapse_codes [ index ] = backward_codes [ index ]
- synapse_messages [index] = backward_messages [ index ]
-
- # ========================================
- # ==== Catch backward request timeouts ====
- # ========================================
- except concurrent.futures.TimeoutError:
- code = bittensor.proto.ReturnCode.Timeout
- call_time = clock.time() - start_time
- message = "Request reached timeout"
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], bittensor.proto.ReturnCode.Timeout, request.synapses
-
- # ==================================
- # ==== Catch unknown exceptions ====
- # ==================================
- except Exception as e:
- code = bittensor.proto.ReturnCode.UnknownException
- call_time = clock.time() - start_time
- message = str ( e )
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_codes_stats_and_logs()
- return [], bittensor.proto.ReturnCode.UnknownException, request.synapses
-
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_codes_stats_and_logs()
- return [], synapse_codes[0], request.synapses
-
- # ==============================
- # ==== Finalize call times =====
- # ==============================
- for index, _ in enumerate( synapses ):
- if synapse_codes[index] == bittensor.proto.ReturnCode.Success:
- synapse_call_times[index] = clock.time() - start_time
-
- finalize_codes_stats_and_logs()
- return [], bittensor.proto.ReturnCode.Success, request.synapses
-
- def default_forward_callback(self, inputs_x:torch.FloatTensor, synapses=[], hotkey = None):
- """
- The default forward callback when no callback is attached: Is used to call specific synapse functions
-
- Args:
- inputs_x (:obj:`torch.FloatTensor`, `required`):
- The inputs that will be passed to the synapse functions
-
- synapses (:obj: list of bittensor.proto.SynapseArgs, 'Optional')
- The proto message that contains additional args for individual synapse functions
-
- hotkey (:obj: str of the hotkey, 'Optional')
- The hotkey of the validator who sent the request
-
- Returns:
- response_tensors: (:obj: list of bittensor.proto.Tensor, `required`):
- serialized tensor response from the nucleus call or None.
- response_codes: (:obj: list of bittensor.proto.ReturnCode, `required`)
- return code associated with forward call i.e. Success of Timeout.
- response_messages: (:obj: list of strings, `required`)
- return message associated with synapse call
- """
- # --- initialize response variables ---
- response_tensors = []
- response_codes = []
- response_messages = []
- model_output = None
-
- # --- calling attached synapses ---
- for index, synapse in enumerate(synapses):
- try:
- synapse_check = self.synapse_checks(synapse, hotkey, inputs_x)
-
- if synapse.synapse_type in self.synapse_callbacks and self.synapse_callbacks[synapse.synapse_type] != None and synapse_check:
- message, model_output, response_tensor = self.synapse_callbacks[synapse.synapse_type](inputs_x[index], synapse, model_output)
- response_tensors.append(response_tensor)
- response_codes.append(bittensor.proto.ReturnCode.Success)
- response_messages.append('Success' if message is None else message)
-
- elif not synapse_check:
- response_tensors.append(None)
- response_codes.append(bittensor.proto.ReturnCode.UnknownException)
- response_messages.append('Synapse Check Failed')
-
- else:
- response_tensors.append(None)
- response_codes.append(bittensor.proto.ReturnCode.NotImplemented)
- response_messages.append('Not Implemented')
-
- except Exception as e:
- # --- Exception Hit in Synapse ---
- response_tensors.append(None)
- response_codes.append(bittensor.proto.ReturnCode.UnknownException)
- response_messages.append(str(e))
-
- return response_tensors, response_codes, response_messages
-
- def default_backward_callback(self, inputs_x:torch.FloatTensor, grads_dy:torch.FloatTensor, synapses=[] ):
- raise Exception('No Backward Function Attached')
-
- def attach_forward_callback(self, forward_callback: Callable[ [str, torch.Tensor, int], torch.Tensor ]):
- """ Assigns the forward_callback.
-
- Returns:
- forward_callback (:callabl:`Callable[ [str, torch.Tensor, int], torch.Tensor `, `required`):
- Forward function called on recieving a forward request.
- """
- bittensor.axon.check_forward_callback(forward_callback)
- self.forward_callback = forward_callback
-
- def attach_synapse_callback(self, synapse_callback: Callable[[str, torch.Tensor, int],torch.Tensor], synapse_type ):
- """ Assigns the callback to a specific synapse.
-
- Args:
- synapse_callback (:callabl:`Callable[ [str, torch.Tensor, int], torch.Tensor `, `required`):
- function called for a specific synapse.
- """
- self.synapse_callbacks[synapse_type] = synapse_callback
-
- def attach_backward_callback(self, backward_callback: Callable[ [str, torch.Tensor, torch.Tensor, int], torch.Tensor ] ):
- """ Assigns the backward_callback call to this neuron.
-
- Returns:
- backward_callback (:callabl:`Callable[ [torch.Tensor, torch.Tensor], torch.Tensor `, `required`):
- Backward callback called on recieving a backward request.
- """
- bittensor.axon.check_backward_callback(backward_callback)
- self.backward_callback = backward_callback
-
- def __del__(self):
- r""" Called when this axon is deleted, ensures background threads shut down properly.
- """
- self.stop()
-
- def serve(
- self,
- use_upnpc: bool = False,
- subtensor: 'bittensor.Subtensor' = None,
- network: str = None,
- chain_endpoint: str = None,
- prompt: bool = False
- ) -> 'Axon':
- r""" Subscribes this Axon servicing endpoint to the passed network using it's wallet.
- Args:
- use_upnpc (:type:bool, `optional`):
- If true, serves the axon attempts port forward through your router before
- subscribing.
- subtensor (:obj:`bittensor.Subtensor`, `optional`):
- Chain connection through which to serve.
- network (default='local', type=str)
- If subtensor is not set, uses this network flag to create the subtensor connection.
- chain_endpoint (default=None, type=str)
- Overrides the network argument if not set.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
-
- """
- if subtensor == None: subtensor = bittensor.subtensor( network = network, chain_endpoint = chain_endpoint)
- serv_success = subtensor.serve_axon( axon = self, use_upnpc = use_upnpc, prompt = prompt )
- if not serv_success:
- raise RuntimeError('Failed to serve neuron.')
- return self
-
- def start(self) -> 'Axon':
- r""" Starts the standalone axon GRPC server thread.
- """
- if self.server != None:
- self.server.stop( grace = 1 )
- logger.success("Axon Stopped:".ljust(20) + "{}", self.ip + ':' + str(self.port))
-
- self.server.start()
- logger.success("Axon Started:".ljust(20) + "{}", self.ip + ':' + str(self.port))
- self.started = True
-
- # Switch prometheus ENUM.
- if self.prometheus_level != bittensor.prometheus.level.OFF.name:
- PROM_axon_is_started.state('started')
-
- return self
-
- def stop(self) -> 'Axon':
- r""" Stop the axon grpc server.
- """
- if self.server != None:
- self.server.stop( grace = 1 )
- logger.success("Axon Stopped:".ljust(20) + "{}", self.ip + ':' + str(self.port))
- self.started = False
-
- # Switch prometheus ENUM.
- if self.prometheus_level != bittensor.prometheus.level.OFF.name:
- PROM_axon_is_started.state('stopped')
-
- return self
-
- def _init_stats(self):
- return SimpleNamespace(
- # Total requests.
- total_requests = 0,
- # Total Codes.
- total_codes = {
- bittensor.proto.ReturnCode.Name(1):0,
- bittensor.proto.ReturnCode.Name(2):0,
- },
- # Total Successes.
- total_successes = 0,
- # Requests per pubkey.
- requests_per_pubkey = {},
- # Success per pubkey.
- successes_per_pubkey = {},
- # Codes recieved per pubkey.
- codes_per_pubkey = {}
- )
-
- def update_stats_for_request(self, request, code):
- r""" Updates statistics for this request and response.
- Args:
- requests ( bittensor.proto.TensorMessage, `required`):
- The request.
- time (:type:`float`, `required`):
- Length of call in seconds.
- code (:obj:`bittensor.proto.ReturnCode, `required`)
- Return code associated with the call i.e. Success of Timeout.
- """
- self.stats.total_requests += 1
- pubkey = request.hotkey
-
- self.stats.requests_per_pubkey.setdefault(pubkey, 0)
- self.stats.successes_per_pubkey.setdefault(pubkey, 0)
- self.stats.codes_per_pubkey.setdefault(pubkey, {})
- self.stats.total_codes.setdefault(bittensor.proto.ReturnCode.Name( code ), 0)
-
- # Add values.
- self.stats.requests_per_pubkey[ pubkey ] += 1
- self.stats.successes_per_pubkey[ pubkey ] += 1 if code == 1 else 0
- self.stats.total_successes += 1 if code == 1 else 0
-
- self.stats.codes_per_pubkey[ pubkey ].setdefault(bittensor.proto.ReturnCode.Name( code ), 0)
- self.stats.codes_per_pubkey[ pubkey ][bittensor.proto.ReturnCode.Name( code )] += 1
- self.stats.total_codes[bittensor.proto.ReturnCode.Name( code )] += 1
-
-
-
- def to_dataframe ( self, metagraph ):
- r""" Return a stats info as a pandas dataframe indexed by the metagraph or pubkey if not existend.
- Args:
- metagraph: (bittensor.Metagraph):
- Indexes the stats data using uids.
- Return:
- dataframe (:obj:`pandas.Dataframe`)
- """
- # Reindex the pubkey to uid if metagraph is present.
- try:
- index = [ metagraph.hotkeys.index(pubkey) for pubkey in self.stats.requests_per_pubkey.keys() if pubkey in metagraph.hotkeys ]
- columns = [ 'axon_n_requested', 'axon_n_success' ]
- dataframe = pandas.DataFrame(columns = columns, index = index)
- for pubkey in self.stats.requests_per_pubkey.keys():
- if pubkey in metagraph.hotkeys:
- uid = metagraph.hotkeys.index(pubkey)
- dataframe.loc[ uid ] = pandas.Series( {
- 'axon_n_requested': int(self.stats.requests_per_pubkey[pubkey]),
- 'axon_n_success': int(self.stats.requests_per_pubkey[pubkey]),
- } )
- dataframe['uid'] = dataframe.index
- return dataframe
-
- except Exception as e:
- bittensor.logging.error(prefix='failed axon.to_dataframe()', sufix=str(e))
- return pandas.DataFrame()
\ No newline at end of file
diff --git a/commune/modules/bittensor/bittensor_module.ipynb b/commune/modules/bittensor/bittensor_module.ipynb
deleted file mode 100644
index ad729d04a..000000000
--- a/commune/modules/bittensor/bittensor_module.ipynb
+++ /dev/null
@@ -1,1500 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "7c59dabe-7961-4ba3-b08d-3dfdcacf40d6",
- "metadata": {},
- "source": [
- "# Bittensor Module: Buidl your own Cabal"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e0f9fb24-3f93-489b-bf0f-db3328254d28",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "[WARNING]: failed to patch stdout/stderr for fork-safety: 'OutStream' object\n",
- "has no attribute 'buffer'\n",
- "[WARNING]: failed to reconfigure stdout/stderr with custom encoding error\n",
- "handler: 'OutStream' object has no attribute 'reconfigure'\n"
- ]
- }
- ],
- "source": [
- "import commune as c\n",
- "bt = c.m('bittensor')"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a49abc03",
- "metadata": {},
- "source": [
- "### Config\n",
- "\n",
- "The config specifies the default variables, like what chain you are on, the netuid, the neurons you you can use to mine, etc. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "id": "9a6e948e",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "Munch({'coldkey': 'alice', 'model_name': 'server', 'module': 'BittensorModule', 'netuid': 11, 'network': 'finney', \n",
- "'network2endpoint': Munch({'finney': 'wss://entrypoint-finney.opentensor.ai:443', 'local': 'ws://0.0.0.0:9944', \n",
- "'test': 'wss://test.finney.opentensor.ai:443'}), 'pool_address': None, 'neurons': Munch({'openai': \n",
- "'commune.modules.bittensor.neurons.text.prompting.miners.openai.neuron.OpenAIMiner', 'openai.free': \n",
- "'commune.modules.bittensor.neurons.text.prompting.miners.openai_freew.neuron.OpenAIFreeMiner', 'commune': \n",
- "'commune.modules.bittensor.neurons.text.prompting.miners.commune.neuron.MaoMiner'})})\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;35mMunch\u001b[0m\u001b[1m(\u001b[0m\u001b[1m{\u001b[0m\u001b[32m'coldkey'\u001b[0m: \u001b[32m'alice'\u001b[0m, \u001b[32m'model_name'\u001b[0m: \u001b[32m'server'\u001b[0m, \u001b[32m'module'\u001b[0m: \u001b[32m'BittensorModule'\u001b[0m, \u001b[32m'netuid'\u001b[0m: \u001b[1;36m11\u001b[0m, \u001b[32m'network'\u001b[0m: \u001b[32m'finney'\u001b[0m, \n",
- "\u001b[32m'network2endpoint'\u001b[0m: \u001b[1;35mMunch\u001b[0m\u001b[1m(\u001b[0m\u001b[1m{\u001b[0m\u001b[32m'finney'\u001b[0m: \u001b[32m'wss://entrypoint-finney.opentensor.ai:443'\u001b[0m, \u001b[32m'local'\u001b[0m: \u001b[32m'ws://0.0.0.0:9944'\u001b[0m, \n",
- "\u001b[32m'test'\u001b[0m: \u001b[32m'wss://test.finney.opentensor.ai:443'\u001b[0m\u001b[1m}\u001b[0m\u001b[1m)\u001b[0m, \u001b[32m'pool_address'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'neurons'\u001b[0m: \u001b[1;35mMunch\u001b[0m\u001b[1m(\u001b[0m\u001b[1m{\u001b[0m\u001b[32m'openai'\u001b[0m: \n",
- "\u001b[32m'commune.modules.bittensor.neurons.text.prompting.miners.openai.neuron.OpenAIMiner'\u001b[0m, \u001b[32m'openai.free'\u001b[0m: \n",
- "\u001b[32m'commune.modules.bittensor.neurons.text.prompting.miners.openai_freew.neuron.OpenAIFreeMiner'\u001b[0m, \u001b[32m'commune'\u001b[0m: \n",
- "\u001b[32m'commune.modules.bittensor.neurons.text.prompting.miners.commune.neuron.MaoMiner'\u001b[0m\u001b[1m}\u001b[0m\u001b[1m)\u001b[0m\u001b[1m}\u001b[0m\u001b[1m)\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "c.print(bt.config) # config is in munch by default"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "88ac413d",
- "metadata": {},
- "source": [
- "#### Check the wallets (total, registered, unregistered)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "ba8c4996-feea-4def-a6ca-17b16ec954f6",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "{\n",
- " 'total_keys': [\n",
- " 'alice.0',\n",
- " 'alice.1',\n",
- " 'alice.2',\n",
- " 'alice.3',\n",
- " 'alice.4',\n",
- " 'alice.5',\n",
- " 'alice.6',\n",
- " 'alice.7',\n",
- " 'alice.8',\n",
- " 'alice.9',\n",
- " 'alice.10',\n",
- " 'alice.11',\n",
- " 'alice.12',\n",
- " 'alice.13',\n",
- " 'alice.14',\n",
- " 'alice.15',\n",
- " 'alice.16',\n",
- " 'alice.17',\n",
- " 'alice.18',\n",
- " 'alice.19',\n",
- " 'alice.20',\n",
- " 'alice.21',\n",
- " 'alice.22',\n",
- " 'alice.23',\n",
- " 'alice.24',\n",
- " 'alice.25',\n",
- " 'alice.26',\n",
- " 'alice.27',\n",
- " 'alice.28',\n",
- " 'alice.29',\n",
- " 'alice.30',\n",
- " 'alice.31',\n",
- " 'alice.32',\n",
- " 'alice.33',\n",
- " 'alice.34',\n",
- " 'alice.35',\n",
- " 'alice.36',\n",
- " 'alice.37',\n",
- " 'alice.38',\n",
- " 'alice.39',\n",
- " 'alice.40',\n",
- " 'alice.41',\n",
- " 'alice.42',\n",
- " 'alice.43',\n",
- " 'alice.44',\n",
- " 'alice.45',\n",
- " 'alice.46',\n",
- " 'alice.47',\n",
- " 'alice.48',\n",
- " 'alice.49',\n",
- " 'alice.50',\n",
- " 'alice.51',\n",
- " 'alice.52',\n",
- " 'alice.53',\n",
- " 'alice.54',\n",
- " 'alice.55',\n",
- " 'alice.56',\n",
- " 'alice.57',\n",
- " 'alice.58',\n",
- " 'alice.59',\n",
- " 'alice.60',\n",
- " 'alice.61',\n",
- " 'alice.62',\n",
- " 'alice.63',\n",
- " 'alice.64',\n",
- " 'alice.65',\n",
- " 'alice.66',\n",
- " 'alice.67',\n",
- " 'alice.68',\n",
- " 'alice.69',\n",
- " 'alice.70',\n",
- " 'alice.71',\n",
- " 'alice.72',\n",
- " 'alice.73',\n",
- " 'alice.74',\n",
- " 'alice.75',\n",
- " 'alice.76',\n",
- " 'alice.77',\n",
- " 'alice.78',\n",
- " 'alice.79',\n",
- " 'alice.80',\n",
- " 'alice.81',\n",
- " 'alice.82',\n",
- " 'alice.83',\n",
- " 'alice.84',\n",
- " 'alice.85',\n",
- " 'alice.86',\n",
- " 'alice.87',\n",
- " 'alice.88',\n",
- " 'alice.89',\n",
- " 'alice.90',\n",
- " 'alice.91',\n",
- " 'alice.92',\n",
- " 'alice.93',\n",
- " 'alice.94',\n",
- " 'alice.95',\n",
- " 'alice.96',\n",
- " 'alice.97',\n",
- " 'alice.98',\n",
- " 'alice.99',\n",
- " 'alice.100',\n",
- " 'alice.101',\n",
- " 'alice.102',\n",
- " 'alice.103',\n",
- " 'alice.104',\n",
- " 'alice.105',\n",
- " 'alice.106',\n",
- " 'alice.107',\n",
- " 'alice.108',\n",
- " 'alice.109',\n",
- " 'alice.110',\n",
- " 'alice.111',\n",
- " 'alice.112',\n",
- " 'alice.113',\n",
- " 'alice.114',\n",
- " 'alice.115',\n",
- " 'alice.116',\n",
- " 'alice.117',\n",
- " 'alice.118',\n",
- " 'alice.119',\n",
- " 'alice.120',\n",
- " 'alice.121',\n",
- " 'alice.122',\n",
- " 'alice.123',\n",
- " 'alice.124',\n",
- " 'alice.125',\n",
- " 'alice.126',\n",
- " 'alice.127',\n",
- " 'alice.128',\n",
- " 'alice.129',\n",
- " 'alice.130',\n",
- " 'alice.131',\n",
- " 'alice.132',\n",
- " 'alice.133',\n",
- " 'alice.134',\n",
- " 'alice.135',\n",
- " 'alice.136',\n",
- " 'alice.137',\n",
- " 'alice.138',\n",
- " 'alice.139',\n",
- " 'alice.140',\n",
- " 'alice.141',\n",
- " 'alice.142',\n",
- " 'alice.143',\n",
- " 'alice.144',\n",
- " 'alice.145',\n",
- " 'alice.146',\n",
- " 'alice.147',\n",
- " 'alice.148',\n",
- " 'alice.149',\n",
- " 'alice.150',\n",
- " 'alice.151',\n",
- " 'alice.152',\n",
- " 'alice.153',\n",
- " 'alice.154',\n",
- " 'alice.155',\n",
- " 'alice.156',\n",
- " 'alice.157',\n",
- " 'alice.158',\n",
- " 'alice.159',\n",
- " 'alice.160',\n",
- " 'alice.161',\n",
- " 'alice.162',\n",
- " 'alice.163',\n",
- " 'alice.164',\n",
- " 'alice.165',\n",
- " 'alice.166',\n",
- " 'alice.167',\n",
- " 'alice.168',\n",
- " 'alice.169',\n",
- " 'alice.170',\n",
- " 'alice.171',\n",
- " 'alice.172',\n",
- " 'alice.173',\n",
- " 'alice.174',\n",
- " 'alice.175',\n",
- " 'alice.176',\n",
- " 'alice.177',\n",
- " 'alice.178',\n",
- " 'alice.179',\n",
- " 'alice.180',\n",
- " 'alice.181',\n",
- " 'alice.182',\n",
- " 'alice.183',\n",
- " 'alice.184',\n",
- " 'alice.185',\n",
- " 'alice.186',\n",
- " 'alice.187',\n",
- " 'alice.188',\n",
- " 'alice.189',\n",
- " 'alice.190',\n",
- " 'alice.191',\n",
- " 'alice.192',\n",
- " 'alice.193',\n",
- " 'alice.194',\n",
- " 'alice.195',\n",
- " 'alice.196',\n",
- " 'alice.197',\n",
- " 'alice.198',\n",
- " 'alice.199'\n",
- " ],\n",
- " 'reged': ['alice.0'],\n",
- " 'unreged': [\n",
- " 'alice.1',\n",
- " 'alice.2',\n",
- " 'alice.3',\n",
- " 'alice.4',\n",
- " 'alice.5',\n",
- " 'alice.6',\n",
- " 'alice.7',\n",
- " 'alice.8',\n",
- " 'alice.9',\n",
- " 'alice.10',\n",
- " 'alice.11',\n",
- " 'alice.12',\n",
- " 'alice.13',\n",
- " 'alice.14',\n",
- " 'alice.15',\n",
- " 'alice.16',\n",
- " 'alice.17',\n",
- " 'alice.18',\n",
- " 'alice.19',\n",
- " 'alice.20',\n",
- " 'alice.21',\n",
- " 'alice.22',\n",
- " 'alice.23',\n",
- " 'alice.24',\n",
- " 'alice.25',\n",
- " 'alice.26',\n",
- " 'alice.27',\n",
- " 'alice.28',\n",
- " 'alice.29',\n",
- " 'alice.30',\n",
- " 'alice.31',\n",
- " 'alice.32',\n",
- " 'alice.33',\n",
- " 'alice.34',\n",
- " 'alice.35',\n",
- " 'alice.36',\n",
- " 'alice.37',\n",
- " 'alice.38',\n",
- " 'alice.39',\n",
- " 'alice.40',\n",
- " 'alice.41',\n",
- " 'alice.42',\n",
- " 'alice.43',\n",
- " 'alice.44',\n",
- " 'alice.45',\n",
- " 'alice.46',\n",
- " 'alice.47',\n",
- " 'alice.48',\n",
- " 'alice.49',\n",
- " 'alice.50',\n",
- " 'alice.51',\n",
- " 'alice.52',\n",
- " 'alice.53',\n",
- " 'alice.54',\n",
- " 'alice.55',\n",
- " 'alice.56',\n",
- " 'alice.57',\n",
- " 'alice.58',\n",
- " 'alice.59',\n",
- " 'alice.60',\n",
- " 'alice.61',\n",
- " 'alice.62',\n",
- " 'alice.63',\n",
- " 'alice.64',\n",
- " 'alice.65',\n",
- " 'alice.66',\n",
- " 'alice.67',\n",
- " 'alice.68',\n",
- " 'alice.69',\n",
- " 'alice.70',\n",
- " 'alice.71',\n",
- " 'alice.72',\n",
- " 'alice.73',\n",
- " 'alice.74',\n",
- " 'alice.75',\n",
- " 'alice.76',\n",
- " 'alice.77',\n",
- " 'alice.78',\n",
- " 'alice.79',\n",
- " 'alice.80',\n",
- " 'alice.81',\n",
- " 'alice.82',\n",
- " 'alice.83',\n",
- " 'alice.84',\n",
- " 'alice.85',\n",
- " 'alice.86',\n",
- " 'alice.87',\n",
- " 'alice.88',\n",
- " 'alice.89',\n",
- " 'alice.90',\n",
- " 'alice.91',\n",
- " 'alice.92',\n",
- " 'alice.93',\n",
- " 'alice.94',\n",
- " 'alice.95',\n",
- " 'alice.96',\n",
- " 'alice.97',\n",
- " 'alice.98',\n",
- " 'alice.99',\n",
- " 'alice.100',\n",
- " 'alice.101',\n",
- " 'alice.102',\n",
- " 'alice.103',\n",
- " 'alice.104',\n",
- " 'alice.105',\n",
- " 'alice.106',\n",
- " 'alice.107',\n",
- " 'alice.108',\n",
- " 'alice.109',\n",
- " 'alice.110',\n",
- " 'alice.111',\n",
- " 'alice.112',\n",
- " 'alice.113',\n",
- " 'alice.114',\n",
- " 'alice.115',\n",
- " 'alice.116',\n",
- " 'alice.117',\n",
- " 'alice.118',\n",
- " 'alice.119',\n",
- " 'alice.120',\n",
- " 'alice.121',\n",
- " 'alice.122',\n",
- " 'alice.123',\n",
- " 'alice.124',\n",
- " 'alice.125',\n",
- " 'alice.126',\n",
- " 'alice.127',\n",
- " 'alice.128',\n",
- " 'alice.129',\n",
- " 'alice.130',\n",
- " 'alice.131',\n",
- " 'alice.132',\n",
- " 'alice.133',\n",
- " 'alice.134',\n",
- " 'alice.135',\n",
- " 'alice.136',\n",
- " 'alice.137',\n",
- " 'alice.138',\n",
- " 'alice.139',\n",
- " 'alice.140',\n",
- " 'alice.141',\n",
- " 'alice.142',\n",
- " 'alice.143',\n",
- " 'alice.144',\n",
- " 'alice.145',\n",
- " 'alice.146',\n",
- " 'alice.147',\n",
- " 'alice.148',\n",
- " 'alice.149',\n",
- " 'alice.150',\n",
- " 'alice.151',\n",
- " 'alice.152',\n",
- " 'alice.153',\n",
- " 'alice.154',\n",
- " 'alice.155',\n",
- " 'alice.156',\n",
- " 'alice.157',\n",
- " 'alice.158',\n",
- " 'alice.159',\n",
- " 'alice.160',\n",
- " 'alice.161',\n",
- " 'alice.162',\n",
- " 'alice.163',\n",
- " 'alice.164',\n",
- " 'alice.165',\n",
- " 'alice.166',\n",
- " 'alice.167',\n",
- " 'alice.168',\n",
- " 'alice.169',\n",
- " 'alice.170',\n",
- " 'alice.171',\n",
- " 'alice.172',\n",
- " 'alice.173',\n",
- " 'alice.174',\n",
- " 'alice.175',\n",
- " 'alice.176',\n",
- " 'alice.177',\n",
- " 'alice.178',\n",
- " 'alice.179',\n",
- " 'alice.180',\n",
- " 'alice.181',\n",
- " 'alice.182',\n",
- " 'alice.183',\n",
- " 'alice.184',\n",
- " 'alice.185',\n",
- " 'alice.186',\n",
- " 'alice.187',\n",
- " 'alice.188',\n",
- " 'alice.189',\n",
- " 'alice.190',\n",
- " 'alice.191',\n",
- " 'alice.192',\n",
- " 'alice.193',\n",
- " 'alice.194',\n",
- " 'alice.195',\n",
- " 'alice.196',\n",
- " 'alice.197',\n",
- " 'alice.198',\n",
- " 'alice.199'\n",
- " ]\n",
- "}\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1m{\u001b[0m\n",
- " \u001b[32m'total_keys'\u001b[0m: \u001b[1m[\u001b[0m\n",
- " \u001b[32m'alice.0'\u001b[0m,\n",
- " \u001b[32m'alice.1'\u001b[0m,\n",
- " \u001b[32m'alice.2'\u001b[0m,\n",
- " \u001b[32m'alice.3'\u001b[0m,\n",
- " \u001b[32m'alice.4'\u001b[0m,\n",
- " \u001b[32m'alice.5'\u001b[0m,\n",
- " \u001b[32m'alice.6'\u001b[0m,\n",
- " \u001b[32m'alice.7'\u001b[0m,\n",
- " \u001b[32m'alice.8'\u001b[0m,\n",
- " \u001b[32m'alice.9'\u001b[0m,\n",
- " \u001b[32m'alice.10'\u001b[0m,\n",
- " \u001b[32m'alice.11'\u001b[0m,\n",
- " \u001b[32m'alice.12'\u001b[0m,\n",
- " \u001b[32m'alice.13'\u001b[0m,\n",
- " \u001b[32m'alice.14'\u001b[0m,\n",
- " \u001b[32m'alice.15'\u001b[0m,\n",
- " \u001b[32m'alice.16'\u001b[0m,\n",
- " \u001b[32m'alice.17'\u001b[0m,\n",
- " \u001b[32m'alice.18'\u001b[0m,\n",
- " \u001b[32m'alice.19'\u001b[0m,\n",
- " \u001b[32m'alice.20'\u001b[0m,\n",
- " \u001b[32m'alice.21'\u001b[0m,\n",
- " \u001b[32m'alice.22'\u001b[0m,\n",
- " \u001b[32m'alice.23'\u001b[0m,\n",
- " \u001b[32m'alice.24'\u001b[0m,\n",
- " \u001b[32m'alice.25'\u001b[0m,\n",
- " \u001b[32m'alice.26'\u001b[0m,\n",
- " \u001b[32m'alice.27'\u001b[0m,\n",
- " \u001b[32m'alice.28'\u001b[0m,\n",
- " \u001b[32m'alice.29'\u001b[0m,\n",
- " \u001b[32m'alice.30'\u001b[0m,\n",
- " \u001b[32m'alice.31'\u001b[0m,\n",
- " \u001b[32m'alice.32'\u001b[0m,\n",
- " \u001b[32m'alice.33'\u001b[0m,\n",
- " \u001b[32m'alice.34'\u001b[0m,\n",
- " \u001b[32m'alice.35'\u001b[0m,\n",
- " \u001b[32m'alice.36'\u001b[0m,\n",
- " \u001b[32m'alice.37'\u001b[0m,\n",
- " \u001b[32m'alice.38'\u001b[0m,\n",
- " \u001b[32m'alice.39'\u001b[0m,\n",
- " \u001b[32m'alice.40'\u001b[0m,\n",
- " \u001b[32m'alice.41'\u001b[0m,\n",
- " \u001b[32m'alice.42'\u001b[0m,\n",
- " \u001b[32m'alice.43'\u001b[0m,\n",
- " \u001b[32m'alice.44'\u001b[0m,\n",
- " \u001b[32m'alice.45'\u001b[0m,\n",
- " \u001b[32m'alice.46'\u001b[0m,\n",
- " \u001b[32m'alice.47'\u001b[0m,\n",
- " \u001b[32m'alice.48'\u001b[0m,\n",
- " \u001b[32m'alice.49'\u001b[0m,\n",
- " \u001b[32m'alice.50'\u001b[0m,\n",
- " \u001b[32m'alice.51'\u001b[0m,\n",
- " \u001b[32m'alice.52'\u001b[0m,\n",
- " \u001b[32m'alice.53'\u001b[0m,\n",
- " \u001b[32m'alice.54'\u001b[0m,\n",
- " \u001b[32m'alice.55'\u001b[0m,\n",
- " \u001b[32m'alice.56'\u001b[0m,\n",
- " \u001b[32m'alice.57'\u001b[0m,\n",
- " \u001b[32m'alice.58'\u001b[0m,\n",
- " \u001b[32m'alice.59'\u001b[0m,\n",
- " \u001b[32m'alice.60'\u001b[0m,\n",
- " \u001b[32m'alice.61'\u001b[0m,\n",
- " \u001b[32m'alice.62'\u001b[0m,\n",
- " \u001b[32m'alice.63'\u001b[0m,\n",
- " \u001b[32m'alice.64'\u001b[0m,\n",
- " \u001b[32m'alice.65'\u001b[0m,\n",
- " \u001b[32m'alice.66'\u001b[0m,\n",
- " \u001b[32m'alice.67'\u001b[0m,\n",
- " \u001b[32m'alice.68'\u001b[0m,\n",
- " \u001b[32m'alice.69'\u001b[0m,\n",
- " \u001b[32m'alice.70'\u001b[0m,\n",
- " \u001b[32m'alice.71'\u001b[0m,\n",
- " \u001b[32m'alice.72'\u001b[0m,\n",
- " \u001b[32m'alice.73'\u001b[0m,\n",
- " \u001b[32m'alice.74'\u001b[0m,\n",
- " \u001b[32m'alice.75'\u001b[0m,\n",
- " \u001b[32m'alice.76'\u001b[0m,\n",
- " \u001b[32m'alice.77'\u001b[0m,\n",
- " \u001b[32m'alice.78'\u001b[0m,\n",
- " \u001b[32m'alice.79'\u001b[0m,\n",
- " \u001b[32m'alice.80'\u001b[0m,\n",
- " \u001b[32m'alice.81'\u001b[0m,\n",
- " \u001b[32m'alice.82'\u001b[0m,\n",
- " \u001b[32m'alice.83'\u001b[0m,\n",
- " \u001b[32m'alice.84'\u001b[0m,\n",
- " \u001b[32m'alice.85'\u001b[0m,\n",
- " \u001b[32m'alice.86'\u001b[0m,\n",
- " \u001b[32m'alice.87'\u001b[0m,\n",
- " \u001b[32m'alice.88'\u001b[0m,\n",
- " \u001b[32m'alice.89'\u001b[0m,\n",
- " \u001b[32m'alice.90'\u001b[0m,\n",
- " \u001b[32m'alice.91'\u001b[0m,\n",
- " \u001b[32m'alice.92'\u001b[0m,\n",
- " \u001b[32m'alice.93'\u001b[0m,\n",
- " \u001b[32m'alice.94'\u001b[0m,\n",
- " \u001b[32m'alice.95'\u001b[0m,\n",
- " \u001b[32m'alice.96'\u001b[0m,\n",
- " \u001b[32m'alice.97'\u001b[0m,\n",
- " \u001b[32m'alice.98'\u001b[0m,\n",
- " \u001b[32m'alice.99'\u001b[0m,\n",
- " \u001b[32m'alice.100'\u001b[0m,\n",
- " \u001b[32m'alice.101'\u001b[0m,\n",
- " \u001b[32m'alice.102'\u001b[0m,\n",
- " \u001b[32m'alice.103'\u001b[0m,\n",
- " \u001b[32m'alice.104'\u001b[0m,\n",
- " \u001b[32m'alice.105'\u001b[0m,\n",
- " \u001b[32m'alice.106'\u001b[0m,\n",
- " \u001b[32m'alice.107'\u001b[0m,\n",
- " \u001b[32m'alice.108'\u001b[0m,\n",
- " \u001b[32m'alice.109'\u001b[0m,\n",
- " \u001b[32m'alice.110'\u001b[0m,\n",
- " \u001b[32m'alice.111'\u001b[0m,\n",
- " \u001b[32m'alice.112'\u001b[0m,\n",
- " \u001b[32m'alice.113'\u001b[0m,\n",
- " \u001b[32m'alice.114'\u001b[0m,\n",
- " \u001b[32m'alice.115'\u001b[0m,\n",
- " \u001b[32m'alice.116'\u001b[0m,\n",
- " \u001b[32m'alice.117'\u001b[0m,\n",
- " \u001b[32m'alice.118'\u001b[0m,\n",
- " \u001b[32m'alice.119'\u001b[0m,\n",
- " \u001b[32m'alice.120'\u001b[0m,\n",
- " \u001b[32m'alice.121'\u001b[0m,\n",
- " \u001b[32m'alice.122'\u001b[0m,\n",
- " \u001b[32m'alice.123'\u001b[0m,\n",
- " \u001b[32m'alice.124'\u001b[0m,\n",
- " \u001b[32m'alice.125'\u001b[0m,\n",
- " \u001b[32m'alice.126'\u001b[0m,\n",
- " \u001b[32m'alice.127'\u001b[0m,\n",
- " \u001b[32m'alice.128'\u001b[0m,\n",
- " \u001b[32m'alice.129'\u001b[0m,\n",
- " \u001b[32m'alice.130'\u001b[0m,\n",
- " \u001b[32m'alice.131'\u001b[0m,\n",
- " \u001b[32m'alice.132'\u001b[0m,\n",
- " \u001b[32m'alice.133'\u001b[0m,\n",
- " \u001b[32m'alice.134'\u001b[0m,\n",
- " \u001b[32m'alice.135'\u001b[0m,\n",
- " \u001b[32m'alice.136'\u001b[0m,\n",
- " \u001b[32m'alice.137'\u001b[0m,\n",
- " \u001b[32m'alice.138'\u001b[0m,\n",
- " \u001b[32m'alice.139'\u001b[0m,\n",
- " \u001b[32m'alice.140'\u001b[0m,\n",
- " \u001b[32m'alice.141'\u001b[0m,\n",
- " \u001b[32m'alice.142'\u001b[0m,\n",
- " \u001b[32m'alice.143'\u001b[0m,\n",
- " \u001b[32m'alice.144'\u001b[0m,\n",
- " \u001b[32m'alice.145'\u001b[0m,\n",
- " \u001b[32m'alice.146'\u001b[0m,\n",
- " \u001b[32m'alice.147'\u001b[0m,\n",
- " \u001b[32m'alice.148'\u001b[0m,\n",
- " \u001b[32m'alice.149'\u001b[0m,\n",
- " \u001b[32m'alice.150'\u001b[0m,\n",
- " \u001b[32m'alice.151'\u001b[0m,\n",
- " \u001b[32m'alice.152'\u001b[0m,\n",
- " \u001b[32m'alice.153'\u001b[0m,\n",
- " \u001b[32m'alice.154'\u001b[0m,\n",
- " \u001b[32m'alice.155'\u001b[0m,\n",
- " \u001b[32m'alice.156'\u001b[0m,\n",
- " \u001b[32m'alice.157'\u001b[0m,\n",
- " \u001b[32m'alice.158'\u001b[0m,\n",
- " \u001b[32m'alice.159'\u001b[0m,\n",
- " \u001b[32m'alice.160'\u001b[0m,\n",
- " \u001b[32m'alice.161'\u001b[0m,\n",
- " \u001b[32m'alice.162'\u001b[0m,\n",
- " \u001b[32m'alice.163'\u001b[0m,\n",
- " \u001b[32m'alice.164'\u001b[0m,\n",
- " \u001b[32m'alice.165'\u001b[0m,\n",
- " \u001b[32m'alice.166'\u001b[0m,\n",
- " \u001b[32m'alice.167'\u001b[0m,\n",
- " \u001b[32m'alice.168'\u001b[0m,\n",
- " \u001b[32m'alice.169'\u001b[0m,\n",
- " \u001b[32m'alice.170'\u001b[0m,\n",
- " \u001b[32m'alice.171'\u001b[0m,\n",
- " \u001b[32m'alice.172'\u001b[0m,\n",
- " \u001b[32m'alice.173'\u001b[0m,\n",
- " \u001b[32m'alice.174'\u001b[0m,\n",
- " \u001b[32m'alice.175'\u001b[0m,\n",
- " \u001b[32m'alice.176'\u001b[0m,\n",
- " \u001b[32m'alice.177'\u001b[0m,\n",
- " \u001b[32m'alice.178'\u001b[0m,\n",
- " \u001b[32m'alice.179'\u001b[0m,\n",
- " \u001b[32m'alice.180'\u001b[0m,\n",
- " \u001b[32m'alice.181'\u001b[0m,\n",
- " \u001b[32m'alice.182'\u001b[0m,\n",
- " \u001b[32m'alice.183'\u001b[0m,\n",
- " \u001b[32m'alice.184'\u001b[0m,\n",
- " \u001b[32m'alice.185'\u001b[0m,\n",
- " \u001b[32m'alice.186'\u001b[0m,\n",
- " \u001b[32m'alice.187'\u001b[0m,\n",
- " \u001b[32m'alice.188'\u001b[0m,\n",
- " \u001b[32m'alice.189'\u001b[0m,\n",
- " \u001b[32m'alice.190'\u001b[0m,\n",
- " \u001b[32m'alice.191'\u001b[0m,\n",
- " \u001b[32m'alice.192'\u001b[0m,\n",
- " \u001b[32m'alice.193'\u001b[0m,\n",
- " \u001b[32m'alice.194'\u001b[0m,\n",
- " \u001b[32m'alice.195'\u001b[0m,\n",
- " \u001b[32m'alice.196'\u001b[0m,\n",
- " \u001b[32m'alice.197'\u001b[0m,\n",
- " \u001b[32m'alice.198'\u001b[0m,\n",
- " \u001b[32m'alice.199'\u001b[0m\n",
- " \u001b[1m]\u001b[0m,\n",
- " \u001b[32m'reged'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'alice.0'\u001b[0m\u001b[1m]\u001b[0m,\n",
- " \u001b[32m'unreged'\u001b[0m: \u001b[1m[\u001b[0m\n",
- " \u001b[32m'alice.1'\u001b[0m,\n",
- " \u001b[32m'alice.2'\u001b[0m,\n",
- " \u001b[32m'alice.3'\u001b[0m,\n",
- " \u001b[32m'alice.4'\u001b[0m,\n",
- " \u001b[32m'alice.5'\u001b[0m,\n",
- " \u001b[32m'alice.6'\u001b[0m,\n",
- " \u001b[32m'alice.7'\u001b[0m,\n",
- " \u001b[32m'alice.8'\u001b[0m,\n",
- " \u001b[32m'alice.9'\u001b[0m,\n",
- " \u001b[32m'alice.10'\u001b[0m,\n",
- " \u001b[32m'alice.11'\u001b[0m,\n",
- " \u001b[32m'alice.12'\u001b[0m,\n",
- " \u001b[32m'alice.13'\u001b[0m,\n",
- " \u001b[32m'alice.14'\u001b[0m,\n",
- " \u001b[32m'alice.15'\u001b[0m,\n",
- " \u001b[32m'alice.16'\u001b[0m,\n",
- " \u001b[32m'alice.17'\u001b[0m,\n",
- " \u001b[32m'alice.18'\u001b[0m,\n",
- " \u001b[32m'alice.19'\u001b[0m,\n",
- " \u001b[32m'alice.20'\u001b[0m,\n",
- " \u001b[32m'alice.21'\u001b[0m,\n",
- " \u001b[32m'alice.22'\u001b[0m,\n",
- " \u001b[32m'alice.23'\u001b[0m,\n",
- " \u001b[32m'alice.24'\u001b[0m,\n",
- " \u001b[32m'alice.25'\u001b[0m,\n",
- " \u001b[32m'alice.26'\u001b[0m,\n",
- " \u001b[32m'alice.27'\u001b[0m,\n",
- " \u001b[32m'alice.28'\u001b[0m,\n",
- " \u001b[32m'alice.29'\u001b[0m,\n",
- " \u001b[32m'alice.30'\u001b[0m,\n",
- " \u001b[32m'alice.31'\u001b[0m,\n",
- " \u001b[32m'alice.32'\u001b[0m,\n",
- " \u001b[32m'alice.33'\u001b[0m,\n",
- " \u001b[32m'alice.34'\u001b[0m,\n",
- " \u001b[32m'alice.35'\u001b[0m,\n",
- " \u001b[32m'alice.36'\u001b[0m,\n",
- " \u001b[32m'alice.37'\u001b[0m,\n",
- " \u001b[32m'alice.38'\u001b[0m,\n",
- " \u001b[32m'alice.39'\u001b[0m,\n",
- " \u001b[32m'alice.40'\u001b[0m,\n",
- " \u001b[32m'alice.41'\u001b[0m,\n",
- " \u001b[32m'alice.42'\u001b[0m,\n",
- " \u001b[32m'alice.43'\u001b[0m,\n",
- " \u001b[32m'alice.44'\u001b[0m,\n",
- " \u001b[32m'alice.45'\u001b[0m,\n",
- " \u001b[32m'alice.46'\u001b[0m,\n",
- " \u001b[32m'alice.47'\u001b[0m,\n",
- " \u001b[32m'alice.48'\u001b[0m,\n",
- " \u001b[32m'alice.49'\u001b[0m,\n",
- " \u001b[32m'alice.50'\u001b[0m,\n",
- " \u001b[32m'alice.51'\u001b[0m,\n",
- " \u001b[32m'alice.52'\u001b[0m,\n",
- " \u001b[32m'alice.53'\u001b[0m,\n",
- " \u001b[32m'alice.54'\u001b[0m,\n",
- " \u001b[32m'alice.55'\u001b[0m,\n",
- " \u001b[32m'alice.56'\u001b[0m,\n",
- " \u001b[32m'alice.57'\u001b[0m,\n",
- " \u001b[32m'alice.58'\u001b[0m,\n",
- " \u001b[32m'alice.59'\u001b[0m,\n",
- " \u001b[32m'alice.60'\u001b[0m,\n",
- " \u001b[32m'alice.61'\u001b[0m,\n",
- " \u001b[32m'alice.62'\u001b[0m,\n",
- " \u001b[32m'alice.63'\u001b[0m,\n",
- " \u001b[32m'alice.64'\u001b[0m,\n",
- " \u001b[32m'alice.65'\u001b[0m,\n",
- " \u001b[32m'alice.66'\u001b[0m,\n",
- " \u001b[32m'alice.67'\u001b[0m,\n",
- " \u001b[32m'alice.68'\u001b[0m,\n",
- " \u001b[32m'alice.69'\u001b[0m,\n",
- " \u001b[32m'alice.70'\u001b[0m,\n",
- " \u001b[32m'alice.71'\u001b[0m,\n",
- " \u001b[32m'alice.72'\u001b[0m,\n",
- " \u001b[32m'alice.73'\u001b[0m,\n",
- " \u001b[32m'alice.74'\u001b[0m,\n",
- " \u001b[32m'alice.75'\u001b[0m,\n",
- " \u001b[32m'alice.76'\u001b[0m,\n",
- " \u001b[32m'alice.77'\u001b[0m,\n",
- " \u001b[32m'alice.78'\u001b[0m,\n",
- " \u001b[32m'alice.79'\u001b[0m,\n",
- " \u001b[32m'alice.80'\u001b[0m,\n",
- " \u001b[32m'alice.81'\u001b[0m,\n",
- " \u001b[32m'alice.82'\u001b[0m,\n",
- " \u001b[32m'alice.83'\u001b[0m,\n",
- " \u001b[32m'alice.84'\u001b[0m,\n",
- " \u001b[32m'alice.85'\u001b[0m,\n",
- " \u001b[32m'alice.86'\u001b[0m,\n",
- " \u001b[32m'alice.87'\u001b[0m,\n",
- " \u001b[32m'alice.88'\u001b[0m,\n",
- " \u001b[32m'alice.89'\u001b[0m,\n",
- " \u001b[32m'alice.90'\u001b[0m,\n",
- " \u001b[32m'alice.91'\u001b[0m,\n",
- " \u001b[32m'alice.92'\u001b[0m,\n",
- " \u001b[32m'alice.93'\u001b[0m,\n",
- " \u001b[32m'alice.94'\u001b[0m,\n",
- " \u001b[32m'alice.95'\u001b[0m,\n",
- " \u001b[32m'alice.96'\u001b[0m,\n",
- " \u001b[32m'alice.97'\u001b[0m,\n",
- " \u001b[32m'alice.98'\u001b[0m,\n",
- " \u001b[32m'alice.99'\u001b[0m,\n",
- " \u001b[32m'alice.100'\u001b[0m,\n",
- " \u001b[32m'alice.101'\u001b[0m,\n",
- " \u001b[32m'alice.102'\u001b[0m,\n",
- " \u001b[32m'alice.103'\u001b[0m,\n",
- " \u001b[32m'alice.104'\u001b[0m,\n",
- " \u001b[32m'alice.105'\u001b[0m,\n",
- " \u001b[32m'alice.106'\u001b[0m,\n",
- " \u001b[32m'alice.107'\u001b[0m,\n",
- " \u001b[32m'alice.108'\u001b[0m,\n",
- " \u001b[32m'alice.109'\u001b[0m,\n",
- " \u001b[32m'alice.110'\u001b[0m,\n",
- " \u001b[32m'alice.111'\u001b[0m,\n",
- " \u001b[32m'alice.112'\u001b[0m,\n",
- " \u001b[32m'alice.113'\u001b[0m,\n",
- " \u001b[32m'alice.114'\u001b[0m,\n",
- " \u001b[32m'alice.115'\u001b[0m,\n",
- " \u001b[32m'alice.116'\u001b[0m,\n",
- " \u001b[32m'alice.117'\u001b[0m,\n",
- " \u001b[32m'alice.118'\u001b[0m,\n",
- " \u001b[32m'alice.119'\u001b[0m,\n",
- " \u001b[32m'alice.120'\u001b[0m,\n",
- " \u001b[32m'alice.121'\u001b[0m,\n",
- " \u001b[32m'alice.122'\u001b[0m,\n",
- " \u001b[32m'alice.123'\u001b[0m,\n",
- " \u001b[32m'alice.124'\u001b[0m,\n",
- " \u001b[32m'alice.125'\u001b[0m,\n",
- " \u001b[32m'alice.126'\u001b[0m,\n",
- " \u001b[32m'alice.127'\u001b[0m,\n",
- " \u001b[32m'alice.128'\u001b[0m,\n",
- " \u001b[32m'alice.129'\u001b[0m,\n",
- " \u001b[32m'alice.130'\u001b[0m,\n",
- " \u001b[32m'alice.131'\u001b[0m,\n",
- " \u001b[32m'alice.132'\u001b[0m,\n",
- " \u001b[32m'alice.133'\u001b[0m,\n",
- " \u001b[32m'alice.134'\u001b[0m,\n",
- " \u001b[32m'alice.135'\u001b[0m,\n",
- " \u001b[32m'alice.136'\u001b[0m,\n",
- " \u001b[32m'alice.137'\u001b[0m,\n",
- " \u001b[32m'alice.138'\u001b[0m,\n",
- " \u001b[32m'alice.139'\u001b[0m,\n",
- " \u001b[32m'alice.140'\u001b[0m,\n",
- " \u001b[32m'alice.141'\u001b[0m,\n",
- " \u001b[32m'alice.142'\u001b[0m,\n",
- " \u001b[32m'alice.143'\u001b[0m,\n",
- " \u001b[32m'alice.144'\u001b[0m,\n",
- " \u001b[32m'alice.145'\u001b[0m,\n",
- " \u001b[32m'alice.146'\u001b[0m,\n",
- " \u001b[32m'alice.147'\u001b[0m,\n",
- " \u001b[32m'alice.148'\u001b[0m,\n",
- " \u001b[32m'alice.149'\u001b[0m,\n",
- " \u001b[32m'alice.150'\u001b[0m,\n",
- " \u001b[32m'alice.151'\u001b[0m,\n",
- " \u001b[32m'alice.152'\u001b[0m,\n",
- " \u001b[32m'alice.153'\u001b[0m,\n",
- " \u001b[32m'alice.154'\u001b[0m,\n",
- " \u001b[32m'alice.155'\u001b[0m,\n",
- " \u001b[32m'alice.156'\u001b[0m,\n",
- " \u001b[32m'alice.157'\u001b[0m,\n",
- " \u001b[32m'alice.158'\u001b[0m,\n",
- " \u001b[32m'alice.159'\u001b[0m,\n",
- " \u001b[32m'alice.160'\u001b[0m,\n",
- " \u001b[32m'alice.161'\u001b[0m,\n",
- " \u001b[32m'alice.162'\u001b[0m,\n",
- " \u001b[32m'alice.163'\u001b[0m,\n",
- " \u001b[32m'alice.164'\u001b[0m,\n",
- " \u001b[32m'alice.165'\u001b[0m,\n",
- " \u001b[32m'alice.166'\u001b[0m,\n",
- " \u001b[32m'alice.167'\u001b[0m,\n",
- " \u001b[32m'alice.168'\u001b[0m,\n",
- " \u001b[32m'alice.169'\u001b[0m,\n",
- " \u001b[32m'alice.170'\u001b[0m,\n",
- " \u001b[32m'alice.171'\u001b[0m,\n",
- " \u001b[32m'alice.172'\u001b[0m,\n",
- " \u001b[32m'alice.173'\u001b[0m,\n",
- " \u001b[32m'alice.174'\u001b[0m,\n",
- " \u001b[32m'alice.175'\u001b[0m,\n",
- " \u001b[32m'alice.176'\u001b[0m,\n",
- " \u001b[32m'alice.177'\u001b[0m,\n",
- " \u001b[32m'alice.178'\u001b[0m,\n",
- " \u001b[32m'alice.179'\u001b[0m,\n",
- " \u001b[32m'alice.180'\u001b[0m,\n",
- " \u001b[32m'alice.181'\u001b[0m,\n",
- " \u001b[32m'alice.182'\u001b[0m,\n",
- " \u001b[32m'alice.183'\u001b[0m,\n",
- " \u001b[32m'alice.184'\u001b[0m,\n",
- " \u001b[32m'alice.185'\u001b[0m,\n",
- " \u001b[32m'alice.186'\u001b[0m,\n",
- " \u001b[32m'alice.187'\u001b[0m,\n",
- " \u001b[32m'alice.188'\u001b[0m,\n",
- " \u001b[32m'alice.189'\u001b[0m,\n",
- " \u001b[32m'alice.190'\u001b[0m,\n",
- " \u001b[32m'alice.191'\u001b[0m,\n",
- " \u001b[32m'alice.192'\u001b[0m,\n",
- " \u001b[32m'alice.193'\u001b[0m,\n",
- " \u001b[32m'alice.194'\u001b[0m,\n",
- " \u001b[32m'alice.195'\u001b[0m,\n",
- " \u001b[32m'alice.196'\u001b[0m,\n",
- " \u001b[32m'alice.197'\u001b[0m,\n",
- " \u001b[32m'alice.198'\u001b[0m,\n",
- " \u001b[32m'alice.199'\u001b[0m\n",
- " \u001b[1m]\u001b[0m\n",
- "\u001b[1m}\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "c.print({\n",
- " 'total_keys': bt.keys(),\n",
- " 'reged': bt.reged(),\n",
- " 'unreged': bt.unreged()\n",
- "})"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "666bc503",
- "metadata": {},
- "source": [
- "## Mining"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "id": "e1a76837",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "The defualt netuid is 11\n",
- " \n"
- ],
- "text/plain": [
- "The defualt netuid is \u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "c.print('The defualt netuid is ',bt.default_netuid)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "id": "4ce38cc3",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "Mining with alice.1\n",
- " \n"
- ],
- "text/plain": [
- "Mining with alice.\u001b[1;36m1\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.1::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m1::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.1::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m1::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "unreged = bt.unreged()\n",
- "c.print('Mining with', unreged[0])\n",
- "bt.mine(unreged[0])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "id": "51e711f8",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "alice.0 is already registered on Subtensor(finney, wss://entrypoint-finney.opentensor.ai:443) 11!\n",
- " \n"
- ],
- "text/plain": [
- "alice.\u001b[1;36m0\u001b[0m is already registered on \u001b[1;35mSubtensor\u001b[0m\u001b[1m(\u001b[0mfinney, \u001b[4;94mwss://entrypoint-finney.opentensor.ai:443\u001b[0m\u001b[4;94m)\u001b[0m \u001b[1;36m11\u001b[0m!\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Getting neuron info for 5Fps2wgmx5hHEtgbbkGuL8WRA86ieN597FxSemMJcSJgYCKy on netuid 11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[32mGetting neuron info for 5Fps2wgmx5hHEtgbbkGuL8WRA86ieN597FxSemMJcSJgYCKy on netuid \u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.0::finney::11 Device: cpu Axon_port: 3164, Prom_port: 0\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m0::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m3164\u001b[0m, Prom_port: \u001b[1;36m0\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.0::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m0::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.0::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m0::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.1::finney::11 Device: cpu Axon_port: 4418, Prom_port: 3418\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m1::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4418\u001b[0m, Prom_port: \u001b[1;36m3418\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.1::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m1::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.1::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m1::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.2::finney::11 Device: cpu Axon_port: 4506, Prom_port: 3506\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m2::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4506\u001b[0m, Prom_port: \u001b[1;36m3506\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.2::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m2::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.2::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m2::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.3::finney::11 Device: cpu Axon_port: 4084, Prom_port: 3084\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m3::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4084\u001b[0m, Prom_port: \u001b[1;36m3084\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.3::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m3::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.3::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m3::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.4::finney::11 Device: cpu Axon_port: 4104, Prom_port: 3104\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m4::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4104\u001b[0m, Prom_port: \u001b[1;36m3104\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.4::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m4::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.4::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m4::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.5::finney::11 Device: cpu Axon_port: 4179, Prom_port: 3179\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m5::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4179\u001b[0m, Prom_port: \u001b[1;36m3179\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.5::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m5::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.5::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m5::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.6::finney::11 Device: cpu Axon_port: 4538, Prom_port: 3538\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m6::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4538\u001b[0m, Prom_port: \u001b[1;36m3538\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.6::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m6::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.6::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m6::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.7::finney::11 Device: cpu Axon_port: 4432, Prom_port: 3432\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m7::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4432\u001b[0m, Prom_port: \u001b[1;36m3432\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.7::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m7::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.7::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m7::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.8::finney::11 Device: cpu Axon_port: 4275, Prom_port: 3275\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m8::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4275\u001b[0m, Prom_port: \u001b[1;36m3275\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.8::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m8::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.8::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m8::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Deploying -> Miner: miner::alice.9::finney::11 Device: cpu Axon_port: 4355, Prom_port: 3355\n",
- " \n"
- ],
- "text/plain": [
- "Deploying -> Miner: miner::alice.\u001b[1;92m9::f\u001b[0minney::\u001b[1;36m11\u001b[0m Device: cpu Axon_port: \u001b[1;36m4355\u001b[0m, Prom_port: \u001b[1;36m3355\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Launching class:BittensorModule name:miner::alice.9::finney::11 fn:mine mode:pm2\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[1;36mLaunching\u001b[0m\u001b[32m \u001b[0m\u001b[1;33mclass:BittensorModule\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mname\u001b[0m\u001b[32m:miner::alice.\u001b[0m\u001b[1;92m9::f\u001b[0m\u001b[32minney::\u001b[0m\u001b[1;36m11\u001b[0m\u001b[32m \u001b[0m\u001b[1;37mfn\u001b[0m\u001b[32m:mine \u001b[0m\u001b[1;37mmode\u001b[0m\u001b[32m:pm2\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "ERROR: No pm2 processes found for miner::alice.9::finney::11\n",
- " \n"
- ],
- "text/plain": [
- "\u001b[31mERROR: No pm2 processes found for miner::alice.\u001b[0m\u001b[1;92m9::f\u001b[0m\u001b[31minney::\u001b[0m\u001b[1;36m11\u001b[0m\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "Max miners reached\n",
- " \n"
- ],
- "text/plain": [
- "Max miners reached\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "bt.fleet('alice', netuid=11, model='commune', n=10) # or bt.fleet() as this is the default\n"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f8b7bf0d",
- "metadata": {},
- "source": [
- "#### Talk to the network by sampling one of your registered keys"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "7a58e089-5310-46eb-b769-6c767e745a1a",
- "metadata": {
- "tags": []
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Canada is divided into 10 provinces and 3 territories. The provinces are: \\n\\n1. Ontario\\n2. Quebec\\n3. Nova Scotia\\n4. New Brunswick\\n5. Manitoba\\n6. British Columbia\\n7. Prince Edward Island\\n8. Saskatchewan'"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "bt.talk('What is the province of canada?', n=10, timeout=5)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.10.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/commune/modules/bittensor/bittensor_module.py b/commune/modules/bittensor/bittensor_module.py
deleted file mode 100644
index e6a77a47e..000000000
--- a/commune/modules/bittensor/bittensor_module.py
+++ /dev/null
@@ -1,2245 +0,0 @@
-
-import torch
-import os,sys
-import asyncio
-from transformers import AutoConfig
-import commune as c
-c.new_event_loop()
-
-import bittensor
-from typing import List, Union, Optional, Dict
-from munch import Munch
-import time
-import streamlit as st
-
-class BittensorModule(c.Module):
- default_config = c.get_config('bittensor')
- default_coldkey = default_config['coldkey']
- default_network = default_config['network']
- wallets_path = os.path.expanduser('~/.bittensor/wallets/')
- default_model = default_config['model']
- default_netuid = default_config['netuid']
- network2endpoint = default_config['network2endpoint']
- default_pool_address = default_config['pool_address']
- chain_repo = f'{c.repo_path}/repos/subtensor'
-
- def __init__(self,
- wallet:Union[bittensor.wallet, str] = None,
- network: Union[bittensor.subtensor, str] =default_network,
- netuid: int = default_netuid,
- config = None,
- ):
- self.set_config(config)
- self.set_subtensor(network=network, netuid=netuid)
- self.set_wallet(wallet)
-
-
- @classmethod
- def networks(cls):
- networks = list(cls.network2endpoint.keys())
- return networks
-
-
- @classmethod
- def get_endpoint(cls, network:str):
- return cls.network2endpoint.get(network, None)
-
-
- @classmethod
- def is_endpoint(cls, endpoint):
- # TODO: check if endpoint is valid, can be limited to just checking if it is a string
- return bool(':' in endpoint and cls.is_number(endpoint.split(':')[-1]))
-
- @classmethod
- def get_subtensor(cls, network:Union[str, bittensor.subtensor]='local') -> bittensor.subtensor:
- if network == None:
- network = cls.default_network
- if isinstance(network, str):
- endpoint = cls.network2endpoint[network]
- subtensor = bittensor.subtensor(chain_endpoint=endpoint)
- else:
- subtensor = network
-
- return subtensor
-
-
- @classmethod
- def get_metagraph(cls,
- netuid = default_netuid,
- network=default_network,
- subtensor = None,
- sync:bool = False,
- load:bool = True,
- save:bool = False,
- block:bool = None):
-
- if subtensor == None:
- subtensor = cls.get_subtensor(network=network)
-
- netuid = cls.get_netuid(netuid)
-
- try:
- metagraph = bittensor.metagraph(subtensor=subtensor, netuid=netuid)
- except TypeError as e:
- metagraph = bittensor.metagraph(netuid=netuid)
-
-
- if save:
- load = False
- if load:
- try:
- metagraph.load()
- save= sync = False
- except FileNotFoundError as e:
- c.print(e, color='red')
- save = sync = True
-
-
-
- if sync:
- metagraph.sync( block=block)
-
- if save:
- metagraph.save()
- return metagraph
-
- meta = get_metagraph
-
- @classmethod
- def set_default(cls,**kwargs):
- config = cls.config()
- for key, value in kwargs.items():
- if key in config:
- assert isinstance(value, type(config[key])), f'Expected {key} to be of type {type(config[key])}, got {type(value)}'
- config[key] = value
-
- cls.save_config(config)
-
-
-
- def set_subtensor(self, network:str=None, netuid:int=None):
-
- self.subtensor = self.get_subtensor(network)
- self.metagraph = self.get_metagraph(subtensor=self.subtensor, netuid=netuid)
-
-
-
- return self.subtensor
-
- def set_wallet(self, wallet=None)-> bittensor.Wallet:
- ''' Sets the wallet for the module.'''
- self.wallet = self.get_wallet(wallet)
- return self.wallet
-
- @classmethod
- def get_wallet(cls, wallet:Union[str, bittensor.wallet]='ensemble.1') -> bittensor.wallet:
- if wallet is None:
- wallet =cls.default_coldkey
- if isinstance(wallet, str):
- if len(wallet.split('.')) == 2:
- name, hotkey = wallet.split('.')
- wallet =bittensor.wallet(name=name, hotkey=hotkey)
- elif len(wallet.split('.')) == 1:
- name = wallet
- wallet =bittensor.wallet(name=name)
- else:
- raise NotImplementedError(wallet)
-
-
- elif isinstance(wallet, bittensor.Wallet):
- wallet = wallet
- else:
- raise NotImplementedError(wallet)
-
- return wallet
- def resolve_subtensor(self, subtensor: 'Subtensor' = None) -> 'Subtensor':
- if isinstance(subtensor, str):
- subtensor = self.get_subtensor(network=subtensor)
- if subtensor is None:
- subtensor = self.subtensor
- return subtensor
-
-
- def resolve_netuid(self, netuid: int = None) -> int:
- if netuid is None:
- netuid = self.netuid
- return netuid
- @classmethod
- def get_netuid(cls, netuid: int = None) -> int:
- if netuid is None:
- netuid = cls.default_netuid
- return netuid
-
- _neurons_cache = {}
-
-
-
-
- @classmethod
- def get_neurons(cls,
- netuid: int = default_netuid,
- cache:bool = True,
- subtensor: 'Subtensor' = None,
- key: str = None,
- index: List[int] = None,
- **kwargs
- ) -> List['Neuron']:
- neurons = None
- if cache:
- neurons = cls._neurons_cache.get(netuid, None)
-
- if neurons is None:
- neurons = cls.get_metagraph(subtensor=subtensor, netuid=netuid, **kwargs).neurons
-
- if cache:
- cls._neurons_cache[netuid] = neurons
-
- if key is not None:
- if isinstance(key, list):
- neurons = [{k:getattr(n, k) for k in key} for n in neurons]
- elif isinstance(key, str):
- neurons = [getattr(n, key) for n in neurons]
- else:
- raise NotImplemented
-
-
-
- if index != None:
- if isinstance(index, int):
- if index < 0:
- index = len(neurons) + index
- neurons = neurons[index]
-
- if isinstance(index,list) and len(index) == 2:
- neurons = neurons[index[0]:index[1]]
-
- return neurons
-
- neurons = get_neurons
-
- @classmethod
- def hotkey2stats(cls, *args, key=['emission', 'incentive','dividends'], **kwargs):
- key = list(set(key + ['hotkey']))
- neurons = cls.neurons(*args,key=key,**kwargs)
- return {n['hotkey']: n for n in neurons}
-
-
- @classmethod
- def get_neuron(cls, wallet=None, netuid: int = None, subtensor=None):
- wallet = cls.get_wallet(wallet)
- netuid = cls.get_netuid(netuid)
- neuron_info = cls.munch({'axon_info': {}, 'prometheus_info': {}})
-
- c.print(f'Getting neuron info for {wallet.hotkey.ss58_address} on netuid {netuid}', color='green')
- neurons = cls.get_neurons(netuid=netuid, subtensor=subtensor)
- for neuron in neurons:
- if wallet.hotkey.ss58_address == neuron.hotkey:
- neuron_info = neuron
- return neuron_info
-
- @classmethod
- def miner_stats(cls, wallet=None, netuid: int = None, subtensor=None):
- wallet = cls.get_wallet(wallet)
- netuid = cls.get_netuid(netuid)
- subtensor = cls.get_subtensor(subtensor)
- neuron_info = wallet.get_neuron(subtensor=subtensor, netuid=netuid)
- neuron_stats = {}
-
- for k, v in neuron_info.__dict__.items():
- if type(v) in [int, float, str]:
- neuron_stats[k] = v
-
- return neuron_stats
-
- # def whitelist(self):
- # return ['miners', 'wallets', 'check_miners', 'reged','unreged', 'stats', 'mems','servers', 'add_server', 'top_neurons']
- @classmethod
- def wallet2neuron(cls, *args, **kwargs):
- kwargs['registered'] = True
- wallet2neuron = {}
-
- async def async_get_neuron(w):
- neuron_info = cls.get_neuron(wallet=w)
- return neuron_info
-
- wallets = cls.wallets(*args, **kwargs)
- jobs = [async_get_neuron(w) for w in wallets]
- neurons = cls.gather(jobs)
-
- wallet2neuron = {w:n for w, n in zip(wallets, neurons)}
-
-
- return wallet2neuron
-
-
-
- @classmethod
- def stats(cls, *args, sigdigs=3,keys=['emission', 'hotkey'], **kwargs):
- import pandas as pd
- wallet2neuron = cls.neurons(keys=keys, **kwargs)
- rows = []
- df = pd.DataFrame(rows)
- df = df.set_index('wallet')
- return df
-
- @classmethod
- def get_stake(cls, hotkey, coldkey = default_coldkey, **kwargs):
- if hotkey in cls.wallets():
- wallet = hotkey
- else:
- wallet = f'{coldkey}.{hotkey}'
- wallet = cls.get_wallet(wallet)
- neuron = cls.get_neuron(wallet=wallet, **kwargs)
-
- return float(neuron.stake)
-
- @classmethod
- def wallet2axon(cls, *args, **kwargs):
-
- wallet2neuron = cls.wallet2neuron(*args, **kwargs)
- wallet2axon = {w:n.axon_info for w, n in wallet2neuron.items()}
-
-
- return wallet2axon
-
- w2a = wallet2axon
-
- @classmethod
- def wallet2port(cls, *args, **kwargs):
-
- wallet2neuron = cls.wallet2neuron(*args, **kwargs)
- wallet2port = {w: n.axon_info.port for w, n in wallet2neuron.items()}
-
-
- return wallet2port
-
- w2p = wallet2port
-
-
- @classmethod
- def zero_emission_miners(cls, coldkey=default_coldkey, **kwargs):
- miners = []
- wallet2stats = cls.wallet2stats(coldkey=coldkey, **kwargs)
- for k, stats in wallet2stats.items():
-
- if stats['emission'] == 0:
- miners.append(k)
-
- return miners
-
- @classmethod
- def stats(cls, **kwargs):
- wallet2stats =cls.wallet2stats(**kwargs)
-
- rows = []
- for w_name, w_stats in wallet2stats.items():
- w_stats['name'] = w_name
- rows.append(w_stats)
-
- df = c.df(rows)
- return df
-
-
- @classmethod
- def wallet2stats(cls, coldkey=default_coldkey, netuid=None , key=['emission', 'incentive']):
- wallet2hotkey = cls.wallet2hotkey(coldkey=coldkey, netuid=netuid)
- hotkey2stats = cls.hotkey2stats(key=key, netuid=netuid)
-
- wallet2stats = {}
- for w,hk in wallet2hotkey.items():
- if hk in hotkey2stats:
- wallet2stats[w] = hotkey2stats[hk]
-
-
- return wallet2stats
-
- w2n = wallet2neuron
-
-
- get_neuron = get_neuron
-
- @classmethod
- def get_axon(cls, wallet=None, netuid: int = None, subtensor=None):
- neuron_info = cls.get_neuron(wallet=wallet, netuid=netuid, subtensor=subtensor)
- axon_info = neuron_info.axon_info
- return axon_info
-
- @classmethod
- def get_prometheus(cls, wallet=None, netuid: int = None, subtensor=None):
- subtensor = cls.get_subtensor(subtensor)
- neuron_info= cls.get_neuron(wallet=wallet, netuid=netuid)
-
- prometheus_info = neuron_info.prometheus_info
- return prometheus_info
-
-
-
- @property
- def neuron_info(self):
- return self.get_neuron(subtensor=self.subtensor, netuid=self.netuid, wallet=self.wallet)
-
- @property
- def axon_info(self):
- return self.get_axon(subtensor=self.subtensor, netuid=self.netuid, wallet=self.wallet)
-
- @property
- def prometheus_info(self):
- return self.get_prometheus(subtensor=self.subtensor, netuid=self.netuid, wallet=self.wallet)
-
- # def get_axon_port(self, wallet=None, netuid: int = None):
- # netuid = self.resolve_netuid(netuid)
- # return self.get_neuron(wallet=wallet, netuid=netuid ).axon_info.port
-
- # def get_prometheus_port(self, wallet=None, netuid: int = None):
- # netuid = self.resolve_netuid(netuid)
- # return self.get_neuron(wallet=wallet, netuid=netuid ).axon_info.port
-
-
-
- @classmethod
- def walk(cls, path:str) -> List[str]:
- import os
- path_list = []
- for root, dirs, files in os.walk(path):
- if len(dirs) == 0 and len(files) > 0:
- for f in files:
- path_list.append(os.path.join(root, f))
- return path_list
- @classmethod
- def wallet_paths(cls):
- wallet_list = cls.ls(cls.wallets_path, recursive=True)
- sorted(wallet_list)
- return wallet_list
-
-
-
-
- @classmethod
- def wallets(cls,
- search = None,
- registered=False,
- unregistered=False,
- mode = 'name',
- coldkey = default_coldkey,
- subtensor=default_network,
- netuid:int=default_netuid,
- registered_hotkeys = None
- ):
-
- if unregistered:
- registered = False
- elif registered:
- unregistered = False
- wallets = []
-
- if coldkey == None:
- coldkeys = cls.coldkeys()
- elif isinstance(coldkey, str):
- coldkeys = [coldkey]
-
- for ck in coldkeys:
- for hk in cls.hotkeys(ck):
- wallet = f'{ck}.{hk}'
-
- if search is not None:
- if not wallet.startswith(search):
- continue
-
- wallet_obj = cls.get_wallet(wallet)
- if registered or unregistered:
- if registered_hotkeys == None:
- registered_hotkeys = cls.get_neurons(subtensor=subtensor, netuid=netuid, key='hotkey')
-
- if registered and wallet_obj.hotkey.ss58_address not in registered_hotkeys:
- continue
- if unregistered and wallet_obj.hotkey.ss58_address in registered_hotkeys:
- continue
-
- if mode in ['obj', 'object']:
- wallets.append(wallet_obj)
- elif mode in ['name', 'path']:
- wallets.append(wallet)
- elif mode in ['address', 'addy','hk']:
- wallets.append(wallet_obj.hotkey.ss58_address)
- else:
- raise ValueError(f'Invalid mode: {mode}')
-
-
- return wallets
-
-
-
- keys = wallets
-
-
-
- @classmethod
- def registered_wallets(cls, search=None, subtensor=default_network, netuid:int=None):
- wallets = cls.wallets(search=search,registered=True, subtensor=subtensor, netuid=netuid)
- return wallets
-
- keys = wallets
- @classmethod
- def registered_hotkeys(cls, coldkey=default_coldkey, subtensor=default_network, netuid:int=None):
- hks = [w.split('.')[-1] for w in cls.wallets(search=coldkey,registered=True, subtensor=subtensor, netuid=netuid)]
- return hks
-
- reged = registered_wallets
- @classmethod
- def unregistered_wallets(cls, search=None, subtensor=default_network, netuid:int=None):
- wallets = cls.wallets(search=search,unregistered=True, subtensor=subtensor, netuid=netuid)
- return wallets
-
- unreged = unregistered_wallets
-
- @classmethod
- def wallet2hotkey(cls, *args, **kwargs):
- kwargs['mode'] = 'object'
- wallets = cls.wallets(*args, **kwargs)
-
- return {w.name+'.'+w.hotkey_str: w.hotkey.ss58_address for w in wallets}
-
-
- @classmethod
- def hotkey2miner(cls, *args, **kwargs):
- kwargs['mode'] = 'object'
- wallet2hotkey = cls.wallet2hotkeys()
-
-
- return {w.name+'.'+w.hotkey_str: w.hotkey.ss58_address for w in wallets}
-
- @classmethod
- def unregistered_hotkeys(cls, coldkey=default_coldkey, subtensor=default_network, netuid:int=None):
- return [w.split('.')[-1] for w in cls.unregistered_wallets(search=coldkey, subtensor=subtensor, netuid=netuid)]
- unreged_hotkeys = unreged_hks = unregistered_hotkeys
- @classmethod
- def wallet2path(cls, search = None):
- wallets = cls.wallets()
- wallet2path = {}
- for wallet in wallets:
- ck, hk = wallet.split('.')
- if search is not None:
- if search not in wallet:
- continue
-
- wallet2path[wallet] = os.path.join(cls.wallets_path, ck, 'hotkeys', hk)
-
-
- return wallet2path
-
-
- @classmethod
- def get_wallet_path(cls, wallet):
- ck, hk = wallet.split('.')
- return os.path.join(cls.wallets_path, ck, 'hotkeys', hk)
-
- @classmethod
- def rm_wallet(cls, wallet):
- wallet2path = cls.wallet2path()
- assert wallet in wallet2path, f'Wallet {wallet} not found in {wallet2path.keys()}'
- cls.rm(wallet2path[wallet])
-
- return {'wallets': cls.wallets(), 'msg': f'wallet {wallet} removed'}
-
- @classmethod
- def rename_coldkey(cls, coldkey1, coldkey2):
- coldkey1_path = cls.coldkey_dir_path(coldkey1)
- cls.print(coldkey1_path)
- assert os.path.isdir(coldkey1_path)
- coldkey2_path = os.path.dirname(coldkey1_path) + '/'+ coldkey2
-
- cls.print(f'moving {coldkey1} ({coldkey1_path}) -> {coldkey2} ({coldkey2_path})')
- cls.mv(coldkey1_path,coldkey2_path)
-
- @classmethod
- def rename_wallet(cls, wallet1, wallet2):
- wallet1_path = cls.get_wallet_path(wallet1)
- wallet2_path = cls.get_wallet_path(wallet2)
- cls.print(f'Renaming {wallet1} to {wallet2}')
-
-
- cls.mv(wallet1_path, wallet2_path)
- return [wallet1, wallet2]
-
- @classmethod
- def coldkey_path(cls, coldkey):
- coldkey_path = os.path.join(cls.wallets_path, coldkey)
- return coldkey_path + '/coldkey'
- @classmethod
- def hotkey_path(cls, hotkey, coldkey=default_coldkey):
- coldkey_path = os.path.join(cls.wallets_path, coldkey)
- return coldkey_path + '/hotkeys/' + str(hotkey)
-
-
- @classmethod
- def coldkey_dir_path(cls, coldkey):
- return os.path.dirname(cls.coldkey_path(coldkey))
-
-
- get_coldkey_path = coldkey_path
- @classmethod
- def coldkeypub_path(cls, coldkey):
- coldkey_path = os.path.join(cls.wallets_path, coldkey)
- return coldkey_path + '/coldkeypub.txt'
-
- def rm_wallets(cls, *wallets, **kwargs):
- for w in wallets:
- cls.rm_wallet(w, **kwargs)
-
- return cls.wallets()
- @classmethod
- def wallet_path(cls, wallet):
- return cls.wallet2path().get(wallet)
-
- @classmethod
- def rm_coldkey(cls,*coldkeys):
-
- coldkeys_removed = []
- for coldkey in coldkeys:
- coldkey = str(coldkey)
-
- if coldkey in cls.coldkeys():
- coldkey_path = cls.coldkey_dir_path(coldkey)
- cls.rm(coldkey_path)
- coldkeys_removed.append(coldkey)
- else:
- cls.print(f'Coldkey {coldkey} not found in {cls.coldkeys()}')
-
- return {'msg': f'Coldkeys removed {coldkeys_removed}', 'coldkeys': cls.coldkeys()}
-
-
- @classmethod
- def hotkeys(cls, coldkey=default_coldkey):
- hotkeys = [os.path.basename(p) for p in cls.ls(os.path.join(cls.wallets_path, coldkey, 'hotkeys'))]
-
-
- if all([c.is_number(hk) for hk in hotkeys]):
- hotkeys = [int(hk) for hk in hotkeys]
- hotkeys = sorted(hotkeys)
- hotkeys = [str(hk) for hk in hotkeys]
- else:
- hotkeys = sorted(hotkeys)
-
- return hotkeys
-
- @classmethod
- def coldkeys(cls, wallet='default'):
-
- return [os.path.basename(p)for p in cls.ls(cls.wallets_path)]
-
-
- @classmethod
- def coldkey_exists(cls, wallet='default'):
- return os.path.exists(cls.get_coldkey_path(wallet))
-
- @classmethod
- def list_wallets(cls, registered=True, unregistered=True, output_wallet:bool = True):
- wallet_paths = cls.wallet_paths()
- wallets = [p.replace(cls.wallets_path, '').replace('/hotkeys/','.') for p in wallet_paths]
-
- if output_wallet:
- wallets = [cls.get_wallet(w) for w in wallets]
-
- return wallets
-
- @classmethod
- def wallet_exists(cls, wallet:str):
- wallets = cls.wallets()
- return bool(wallet in wallets)
-
- @classmethod
- def hotkey_exists(cls, coldkey:str, hotkey:str) -> bool:
- hotkeys = cls.hotkeys(coldkey)
- return bool(hotkey in hotkeys)
-
- @classmethod
- def coldkey_exists(cls, coldkey:str) -> bool:
- coldkeys = cls.coldkeys()
- return bool(coldkey in coldkeys)
-
-
-
- # @property
- # def default_network(self):
- # return self.networks()[0]
-
-
- @property
- def network(self):
- return self.subtensor.network
-
- @classmethod
- def is_registered(cls, wallet = None, netuid: int = default_netuid, subtensor: 'Subtensor' = default_network):
-
- netuid = cls.get_netuid(netuid)
- wallet = cls.get_wallet(wallet)
- hotkeys = cls.get_neurons( netuid=netuid, subtensor=subtensor, key='hotkey')
- return bool(wallet.hotkey.ss58_address in hotkeys)
-
-
- @property
- def registered(self):
- return self.is_registered(wallet=self.wallet, netuid=self.netuid, subtensor=self.subtensor)
-
- @classmethod
- def sync(cls, subtensor= None, netuid: int = None, block = None):
- c.print('Syncing...')
- return cls.get_metagraph(netuid=netuid,
- subtensor=subtensor,
- block=block,
- sync=True,
- save=True)
-
- save = sync
- @classmethod
- def metagraph_staleness(cls, metagraph=None,
- subtensor=None, netuid=None):
- if metagraph is None:
- metagraph = cls.get_metagraph(netuid=netuid,
- subtensor=subtensor,
- load=True)
- subtensor = cls.get_subtensor(subtensor)
-
- current_block = subtensor
- block_staleness = current_block - metagraph.block
- return block_staleness.item()
-
- @classmethod
- def sync_loop(cls,subtensor= 'local',
- netuid: int = None,
- block = None,
- remote=False,
- max_metagraph_staleness=10):
- if remote:
- kwargs = c.locals2kwargs(locals())
- kwargs['remote'] = False
- return cls.remote_fn(fn='sync_loop', kwargs=kwargs)
- metagraph_block = 0
- subtensor = cls.get_subtensor(subtensor)
- netuid = cls.get_netuid(netuid)
- prev_metagraph_staleness = 0
- while True:
- metagraph_staleness = cls.metagraph_staleness(subtensor=subtensor, netuid=netuid)
- if metagraph_staleness > max_metagraph_staleness:
- c.print(f'Block staleness {metagraph_staleness} > {max_metagraph_staleness} for {subtensor} {netuid}. Syncing')
- metagraph = cls.get_metagraph(netuid=netuid,
- subtensor=subtensor,
- sync=True,
- save=True)
- else:
- if prev_metagraph_staleness != metagraph_staleness:
- prev_metagraph_staleness = metagraph_staleness
- c.print(f'Block staleness {metagraph_staleness} < {max_metagraph_staleness} for {subtensor} {netuid}. Sleeping')
-
-
-
-
-
- def wait_until_registered(self, netuid: int = None, wallet: 'Wallet'=None, interval:int=60):
- seconds_waited = 0
- # loop until registered.
- while not self.is_registered( netuid=netuid, wallet=wallet, subtensor=self.subtensor):
- # sleep then sync
- self.print(f'Waiting for registering {seconds_waited} seconds', color='purple')
- self.sleep(interval)
- seconds_waited += interval
- self.sync(netuid=netuid)
-
-
- # @classmethod
- # def dashboard(cls):
-
- # st.set_page_config(layout="wide")
- # self = cls(wallet='collective.0', network=default_network)
-
- # with st.sidebar:
- # self.streamlit_sidebar()
-
- # st.write(f'# BITTENSOR DASHBOARD {self.network}')
- # wallets = self.list_wallets(output_wallet=True)
-
- # st.write(wallets[0].__dict__)
-
- # # self.register()
- # # st.write(self.run_miner('fish', '100'))
-
- # # self.streamlit_neuron_metrics()
-
-
-
- def ensure_env(self):
-
- try:
- import bittensor
- except ImportError:
- c.run_command('pip install bittensor')
-
- return cubit
-
-
- try:
- import cubit
- except ImportError:
- c.run_command('pip install https://github.com/opentensor/cubit/releases/download/v1.1.2/cubit-1.1.2-cp310-cp310-linux_x86_64.whl')
-
-
-
- @property
- def default_subnet(self):
- return 3
-
- @classmethod
- def resolve_dev_id(cls, dev_id: Union[int, List[int]] = None):
- if dev_id is None:
- dev_id = c.gpus()
-
- return dev_id
-
- def resolve_wallet(self, wallet=None):
- if isinstance(wallet, str):
- wallet = self.get_wallet(wallet)
- if wallet is None:
- wallet = self.wallet
- return wallet
-
-
- def resolve_wallet_name(self, wallet=None):
- if isinstance(wallet, str):
- wallet = self.get_wallet(wallet)
- if wallet is None:
- wallet = self.wallet
- wallet_name = f'{wallet.name}.{wallet.hotkey_str}'
- return wallet
-
- def register (
- self,
- wallet = None,
- netuid = None,
- subtensor: 'bittensor.Subtensor' = None,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False,
- max_allowed_attempts: int = 3,
- cuda: bool = True,
- dev_id: Union[int, List[int]] = None,
- TPB: int = 256,
- num_processes: Optional[int] = None,
- update_interval: Optional[int] = 50_000,
- output_in_place: bool = True,
- log_verbose: bool = True,
- remote: bool = False,
-
- ) -> 'bittensor.Wallet':
- """ Registers the wallet to chain.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- max_allowed_attempts (int):
- Maximum number of attempts to register the wallet.
- cuda (bool):
- If true, the wallet should be registered on the cuda device.
- dev_id (int):
- The cuda device id.
- TPB (int):
- The number of threads per block (cuda).
- num_processes (int):
- The number of processes to use to register.
- update_interval (int):
- The number of nonces to solve between updates.
- output_in_place (bool):
- If true, the registration output is printed in-place.
- log_verbose (bool):
- If true, the registration output is more verbose.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if cuda:
- assert self.cuda_available()
- # Get chain connection.
- subtensor = self.resolve_subtensor(subtensor)
- netuid = self.resolve_netuid(netuid)
- dev_id = self.resolve_dev_id(dev_id)
- wallet = self.resolve_wallet(wallet)
-
-
- self.print(f'Registering wallet: {wallet.name}::{wallet.hotkey} on {netuid}', 'yellow')
-
- register_kwargs = dict(
- netuid = netuid,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt=prompt, max_allowed_attempts=max_allowed_attempts,
- output_in_place = output_in_place,
- cuda=cuda,
- dev_id=dev_id,
- TPB=TPB,
- num_processes=num_processes,
- update_interval=update_interval,
- log_verbose=log_verbose,
- wallet=wallet
- )
- if remote:
- self.launch(fn='register_wallet',
- name = f'register::{wallet.name}::{wallet.hotkey}',
- kwargs=register_kwargs)
-
- else:
- subtensor.register(**register_kwargs)
-
- return self
-
-
- @classmethod
- def register_loop(cls, *args, **kwargs):
- # c.new_event_loop()
- self = cls(*args, **kwargs)
- wallets = self.list_wallets()
- for wallet in wallets:
- # print(wallet)
- self.set_wallet(wallet)
- self.register(dev_id=c.gpus())
-
-
- @classmethod
- def create_wallets_from_dict(cls,
- wallets: Dict,
- overwrite: bool = True):
-
- '''
- wallet_dict = {
- 'coldkey1': { 'hotkeys': {'hk1': 'mnemonic', 'hk2': 'mnemonic2'}},
- '''
- wallets = {}
- for coldkey_name, hotkey_dict in wallet_dict.items():
- bittensor.wallet(name=coldkey_name).create_from_mnemonic(coldkey, overwrite=overwrite)
- wallets = {coldkey_name: {}}
- for hotkey_name, mnemonic in hotkey_dict.items():
- wallet = bittensor.wallet(name=coldkey_name, hotkey=hotkey_name).regenerate_hotkey(mnemonic=mnemonic, overwrite=overwrite)
- wallets[coldkey_name] = wallet
- @classmethod
- def create_wallets(cls,
- wallets: Union[List[str], Dict] = [f'ensemble.{i}' for i in range(3)],
- coldkey_use_password:bool = False,
- hotkey_use_password:bool = False
- ):
-
- if isinstance(wallets, list):
- for wallet in wallets:
- cls.get_wallet(wallet)
- cls.create_wallet(coldkey=ck, hotkey=hk, coldkey_use_password=coldkey_use_password, hotkey_use_password=hotkey_use_password)
-
- #################
- #### Staking ####
- #################
- @classmethod
- def stake(
- cls,
- hotkey:str,
- coldkey = default_coldkey,
- hotkey_ss58: Optional[str] = None,
- amount: Union['Balance', float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- subtensor = None
- ) -> bool:
- """ Adds the specified amount of stake to passed hotkey uid. """
- wallet = cls.get_wallet(f'{coldkey}.{hotkey}')
- subtensor = cls.get_subtensor(subtensor)
- return subtensor.add_stake(
- wallet = wallet,
- hotkey_ss58 = hotkey_ss58,
- amount = amount,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- @classmethod
- def add_keys(cls, name=default_coldkey,
- coldkey_ss58: Optional[str] = None,
- hotkeys=None ,
- n = 100,
- use_password: bool=False,
- overwrite:bool = False):
- if coldkey_ss58:
- cls.add_coldkeypub(name=name, ss58_address=coldkey_ss58_address, use_password=use_password, overwrite=overwrite)
- cls.add_coldkey(name=name, use_password=use_password, overwrite=overwrite)
- hotkeys = hotkeys if hotkeys!=None else list(range(n))
- for hotkey in hotkeys:
- cls.add_hotkey(coldkey=name, hotkey=hotkey, use_password=use_password, overwrite=overwrite)
-
- return {'msg': f'Added {len(hotkeys)} hotkeys to {name}'}
-
- @classmethod
- def switch_version(cls, version='4.0.1'):
- version = str(version)
- if str(version) == '4':
- version = '4.0.1'
- elif str(version) == '5':
- version = '5.1.0'
- c.cmd(f'pip install bittensor=={version}', verbose=True)
-
- @classmethod
- def setup(cls, network='local'):
- if network == 'local':
- cls.local_node()
- cls.add_keys()
- cls.fleet(network=network)
-
- @classmethod
- def add_coldkey (cls,
- name,
- mnemonic:str = None,
- use_password=False,
- overwrite:bool = False) :
-
- if cls.coldkey_exists(name) and not overwrite:
- cls.print(f'Coldkey {name} already exists', color='yellow')
- return name
- wallet = bittensor.wallet(name=name)
- if not overwrite:
- if cls.coldkey_exists(name):
- return wallet
-
- if mnemonic is None:
- wallet.create_new_coldkey(use_password=use_password, overwrite=overwrite)
- else:
- wallet.regenerate_coldkey(mnemonic=mnemonic, use_password=use_password, overwrite=overwrite)
- return {'msg': f'Coldkey {name} created', 'success': True}
-
- @classmethod
- def add_coldkeypub (cls,name = 'default',
- ss58_address:str = None,
- use_password=False,
- overwrite:bool = True) :
-
- wallet = bittensor.wallet(name=name)
- wallet.regenerate_coldkeypub(ss58_address=ss58_address, overwrite=overwrite)
- return name
-
- @classmethod
- def new_coldkey( cls, name,
- n_words:int = 12,
- use_password: bool = False,
- overwrite:bool = False) -> 'Wallet':
-
- if not overwrite:
- assert not cls.coldkey_exists(name), f'Wallet {name} already exists.'
-
- wallet = bittensor.wallet(name=name)
- wallet.create_new_coldkey(n_words=n_words, use_password=use_password, overwrite=overwrite)
-
-
- @classmethod
- def new_hotkey( cls, name :str,
- hotkey:str,
- n_words:int = 12,
- overwrite:bool = False,
- use_password:bool = False) -> 'Wallet':
- hotkey = str(hotkey)
- assert cls.coldkey_exists(name), f'Wallet {name} does not exist.'
- if not overwrite:
- assert not cls.hotkey_exists(name, hotkey), f'Hotkey {hotkey} already exists.'
-
- wallet = bittensor.wallet(name=name, hotkey=hotkey)
- wallet.create_new_hotkey(n_words=n_words, use_password=use_password, overwrite=overwrite)
-
-
- @classmethod
- def add_hotkeys(cls, coldkey=default_coldkey,hotkeys:list = 10, **kwargs):
- if isinstance(hotkeys, int):
- hotkeys = list(range(hotkeys))
- assert isinstance(hotkeys, list), f'hotkeys must be a list or int, got {type(hotkeys)}'
-
- for hk in hotkeys:
- cls.add_hotkey(coldkey=coldkey, hotkey=hk, **kwargs)
-
-
- @classmethod
- def add_hotkey (cls,
- coldkey = default_coldkey,
- hotkey = None,
- mnemonic:str = None,
- use_password=False,
- overwrite:bool = False) :
- hotkey= str(hotkey)
- coldkey= str(coldkey)
- assert coldkey in cls.coldkeys()
- wallet = f'{coldkey}.{hotkey}'
- if cls.wallet_exists(wallet):
- if not overwrite:
- cls.print(f'Wallet {wallet} already exists.', color='yellow')
- return wallet
- wallet = bittensor.wallet(name=coldkey, hotkey=hotkey)
- if mnemonic is None:
- wallet.create_new_hotkey(use_password=use_password, overwrite=overwrite)
- else:
- wallet.regenerate_hotkey(mnemonic=mnemonic, use_password=use_password, overwrite=overwrite)
- return wallet
-
- @classmethod
- def regen_hotkey (cls,
- hotkey:str,
- coldkey:str =default_coldkey,
- mnemonic:str = None,
- use_password=False,
- overwrite:bool = True) :
-
-
- assert len(name.split('.')) == 2, 'name must be of the form coldkey.hotkey'
- wallet = bittensor.wallet(name=coldkey, hotkey=hotkey)
- wallet.regenerate_coldkey(mnemonic=mnemonic, use_password=use_password, overwrite=overwrite)
- return wallet
-
-
- @classmethod
- def add_wallet(cls,
- wallet: str = 'default.default',
- coldkey : str = None,
- mnemonic: str= None,
- use_password:bool = False,
- overwrite : bool = True,
- ) :
- if len(wallet.split('.')) == 2:
- coldkey, hotkey = wallet.split('.')
- else:
- raise ValueError('wallet must be of the form coldkey.hotkey')
-
- assert isinstance(hotkey, str), 'hotkey must be a string (or None)'
- assert isinstance(coldkey, str), 'coldkey must be a string'
-
- wallet = bittensor.wallet(name=coldkey, hotkey=hotkey)
- if coldkey:
- wallet.create_from_(mnemonic_ck, use_password=use_password, overwrite=overwrite)
- if mnemonic:
- return wallet.regenerate_hotkey(mnemonic=mnemonic, use_password=hotkey_use_password, overwrite=overwrite)
- else:
- return wallet.create(coldkey_use_password=coldkey_use_password, hotkey_use_password=hotkey_use_password)
-
-
- @classmethod
- def register_wallet_params(cls, wallet_name:str, params:dict):
- registered_info = cls.get('registered_info', {})
- registered_info[wallet_name] = params
- cls.put('registered_info', registered_info)
-
- @classmethod
- def unregister_wallet_params(cls, wallet_name:str):
- registered_info = cls.get('registered_info', {})
- if wallet_name in registered_info:
- registered_info.pop(wallet_name)
- cls.put('registered_info', registered_info)
-
- @classmethod
- def registered_wallet_params(cls):
- return cls.get('registered_info', {})
-
- @classmethod
- def register_wallet(
- cls,
- wallet='default.default',
- subtensor: str =default_network,
- netuid: Union[int, List[int]] = default_netuid,
- dev_id: Union[int, List[int]] = None,
- create: bool = True,
- **kwargs
- ):
- params = c.locals2kwargs(locals())
-
-
- self = cls(wallet=wallet,netuid=netuid, subtensor=subtensor)
- # self.sync()
- wallet_name = c.copy(wallet)
- cls.register_wallet_params(wallet_name=wallet_name, params=params)
- try:
- self.register(dev_id=dev_id, **kwargs)
- except Exception as e:
- c.print(e, color='red')
- finally:
- cls.unregister_wallet_params(wallet_name=wallet_name)
-
-
-
-
- # Streamlit Landing Page
- selected_wallets = []
- def streamlit_sidebar(self):
-
- wallets_list = self.list_wallets(output_wallet=False)
-
- wallet = st.selectbox(f'Select Wallets ({wallets_list[0]})', wallets_list, 0)
- self.set_wallet(wallet)
- networks = self.networks()
- network = st.selectbox(f'Select Network ({networks[0]})', networks, 0)
- self.set_subtensor(subtensor=network)
-
- sync_network = st.button('Sync the Network')
- if sync_network:
- self.sync()
-
- st.write(self.wallet)
-
-
- st.metric(label='Balance', value=int(self.balance)/1e9)
-
-
-
- @staticmethod
- def display_metrics_dict(metrics:dict, num_columns=3):
- if metrics == None:
- return
- if not isinstance(metrics, dict):
- metrics = metrics.__dict__
-
- cols = st.columns(num_columns)
-
-
- for i, (k,v) in enumerate(metrics.items()):
-
- if type(v) in [int, float]:
- cols[i % num_columns].metric(label=k, value=v)
-
-
- def streamlit_neuron_metrics(self, num_columns=3):
- if not self.registered:
- st.write(f'## {self.wallet} is not Registered on {self.subtensor.network}')
- self.button['register'] = st.button('Register')
- self.button['burned_register'] = st.button('Burn Register')
-
-
-
- if self.button['register']:
- self.register_wallet()
- if self.button['burned_register']:
- self.burned_register()
-
- neuron_info = self.get_neuron(wallet=self.wallet)
- axon_info = neuron_info.axon_info
- prometheus_info = axon_info.get('prometheus_info', {})
- # with st.expander('Miner', True):
-
- # self.resolve_wallet_name(wallet)
- # miner_kwargs = dict()
-
-
- # axon_port = neuron_info.get('axon_info', {}).get('port', None)
- # if axon_port == None:
- # axon_port = self.free_port()
- # miner_kwargs['axon_port'] = st.number_input('Axon Port', value=axon_port)
-
-
-
- # prometheus_port = prometheus_info.get('port', None)
- # if prometheus_port == None:
- # prometheus_port = axon_port + 1
- # while self.port_used(prometheus_port):
- # prometheus_port = prometheus_port + 1
-
-
-
- # miner_kwargs['prometheus_port'] = st.number_input('Prometheus Port', value=prometheus_port)
- # miner_kwargs['device'] = st.number_input('Device', self.most_free_gpu() )
- # assert miner_kwargs['device'] in c.gpus(), f'gpu {miner_kwargs["device"]} is not available'
- # miner_kwargs['model_name'] = st.text_input('model_name', self.default_model_name )
- # miner_kwargs['remote'] = st.checkbox('remote', False)
-
- # self.button['mine'] = st.button('Start Miner')
-
- # if self.button['mine']:
- # self.mine(**miner_kwargs)
-
- return
-
- neuron_info = self.get_neuron(self.wallet)
- with st.expander('Neuron Stats', False):
- self.display_metrics_dict(neuron_info)
-
-
- with st.expander('Axon Stats', False):
- self.display_metrics_dict(neuron_info.axon_info)
-
- with st.expander('Prometheus Stats', False):
- self.display_metrics_dict(neuron_info.prometheus_info)
-
- @classmethod
- def dashboard(cls):
- st.set_page_config(layout="wide")
- self = cls( )
- self.button = {}
- with st.sidebar:
- self.streamlit_sidebar()
-
-
-
- self.streamlit_neuron_metrics()
- @classmethod
- def balance(cls, wallet=default_coldkey):
- wallet = cls.get_wallet(wallet)
- return wallet.balance
-
-
- @classmethod
- def burned_register (
- cls,
- wallet: 'bittensor.Wallet' = None,
- netuid: int = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = True,
- prompt: bool = False,
- subtensor = None,
- max_fee = 1.0,
- wait_for_fee = True
- ):
- wallet = cls.get_wallet(wallet)
- netuid = cls.get_netuid(netuid)
- subtensor = cls.get_subtensor(subtensor)
- fee = cls.burn_fee(subtensor=subtensor)
- while fee >= max_fee:
- cls.print(f'fee {fee} is too high, max_fee is {max_fee}')
- time.sleep(1)
- fee = cls.burn_fee(subtensor=subtensor)
- if cls.is_registered(wallet=wallet, netuid=netuid, subtensor=subtensor):
- cls.print(f'wallet {wallet} is already registered on {netuid}')
- return True
- subtensor.burned_register(
- wallet = wallet,
- netuid = netuid,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- burn_reg = burned_register
-
- @classmethod
- def burned_register_many(cls, *wallets, **kwargs):
- for wallet in wallets:
- cls.burned_register(wallet=wallet, **kwargs)
-
- burn_reg_many = burned_register_many
-
- @classmethod
- def burned_register_coldkey(cls, coldkey = default_coldkey,
- sleep_interval=3,
- **kwargs):
-
- wallets = cls.unregistered(coldkey)
- if max_wallets == None:
- max_wallets = cls.num_gpus()
-
- # if max_wallets == None:
- wallets = wallets[:max_wallets]
- for wallet in wallets:
- assert cls.wallet_exists(wallet), f'wallet {wallet} does not exist'
- cls.print(f'burned_register {wallet}')
- cls.burned_register(wallet=wallet, **kwargs)
- cls.sleep(sleep_interval)
-
- burn_reg_ck = burned_register_coldkey
-
- @classmethod
- def transfer(cls,
- dest:str,
- amount: Union[float, bittensor.Balance],
- wallet = default_coldkey,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- subtensor: 'bittensor.Subtensor' = None,
- prompt: bool = False,
- min_balance= 0.1,
- gas_fee: bool = 0.0001):
- wallet = cls.get_wallet(wallet)
- balance = cls.get_balance(wallet)
- balance = balance - gas_fee
- if balance < min_balance:
- cls.print(f'Not Enough Balance for Transfer --> Balance ({balance}) < min balance ({min_balance})', color='red')
- return None
- else:
- cls.print(f'Enough Balance for Transfer --> Balance ({balance}) > min balance ({min_balance})')
-
- print(f'balance {balance} amount {amount}')
- if amount == -1:
- amount = balance - gas_fee
-
- assert balance >= amount, f'balance {balance} is less than amount {amount}'
- wallet.transfer(
- dest=dest,
- amount=amount,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization= wait_for_finalization,
- subtensor = subtensor,
- prompt = prompt)
-
- @classmethod
- def get_balance(self, wallet):
- wallet = self.get_wallet(wallet)
- return float(wallet.balance)
-
-
- @classmethod
- def address(cls, wallet = default_coldkey):
- wallet = cls.get_wallet(wallet)
- return wallet.coldkeypub.ss58_address
- ss58 = address
- @classmethod
- def score(cls, wallet='collective.0'):
- cmd = f"grep Loss ~/.pm2/logs/{wallet}.log"+ " | awk -F\| {'print $10'} | awk {'print $2'} | awk '{for(i=1;i<=NF;i++) {sum[i] += $i; sumsq[i] += ($i)^2}} END {for (i=1;i<=NF;i++) {printf \"%f +/- %f \", sum[i]/NR, sqrt((sumsq[i]-sum[i]^2/NR)/NR)}}'"
- print(cmd)
- return cls.cmd(cmd)
-
-
- @classmethod
- def neuron_class(cls, model=default_model, netuid=default_netuid):
- if netuid in [1, 11]:
- neuron_path = cls.getc('neurons').get(model)
- neuron_class = c.import_object(neuron_path)
- else:
- raise ValueError(f'netuid {netuid} not supported')
- return neuron_class
-
-
-
- @classmethod
- def neuron(cls, *args, mode=None, netuid=3, **kwargs):
-
- if netuid == 3:
- neuron = cls.module('bittensor.miner.neuron')(*args, **kwargs)
- elif netuid in [1,11]:
- neuron = cls.import_object('commune.bittensor.neurons.neurons.text.prompting')(*args, **kwargs)
-
- return neuron
-
- @classmethod
- def mine_many(cls, *hotkeys, coldkey=default_coldkey, **kwargs):
- for hk in hotkeys:
- cls.mine(wallet=f'{coldkey}.{hk}', **kwargs)
-
-
-
- @classmethod
- def get_miner_name(cls, wallet:str, network:str, netuid:int) -> str:
- network = cls.resolve_network(network)
- name = f'miner::{wallet}::{network}::{netuid}'
-
- return name
-
-
- @classmethod
- def mine(cls,
- wallet='alice.1',
- network =default_network,
- netuid=default_netuid,
- model = default_model,
- port = None,
- prometheus_port:int = None,
- device:int = None,
- debug = True,
- no_set_weights = True,
- remote:bool = True,
- sleep_interval:int = 2,
- autocast:bool = True,
- burned_register:bool = False,
- logging:bool = True,
- max_fee:int = 2.0,
- refresh=True,
- miner_name:str = None,
- refresh_ports:bool = False,
- vpermit_required: bool = False,
- min_allowed_stake: float = 15000
- ):
-
-
- kwargs = cls.locals2kwargs(locals())
- # resolve the name of the remote function
- if remote:
- if miner_name == None:
- miner_name = cls.get_miner_name(wallet=wallet,
- network=network,
- netuid=netuid)
-
- kwargs['remote'] = False
- return cls.remote_fn(fn='mine',name=miner_name, kwargs=kwargs, refresh=refresh)
-
-
- neuron_class = cls.neuron_class(netuid=netuid, model=model)
- config = neuron_class.config()
- config.merge(bittensor.BaseMinerNeuron.config())
- config.neuron.blacklist.vpermit_required = vpermit_required
- config.neuron.blacklist.min_allowed_stake = min_allowed_stake
- # model things
- config.neuron.no_set_weights = no_set_weights
- config.netuid = netuid
-
- # network
- subtensor = bittensor.subtensor(network=network)
- bittensor.utils.version_checking()
-
-
-
- # wallet
- coldkey, hotkey = wallet.split('.')
- config.wallet.name = coldkey
- config.wallet.hotkey = hotkey
- wallet = bittensor.wallet(config=config)
-
- if cls.is_registered(wallet=wallet, subtensor=subtensor, netuid=netuid):
- cls.print(f'wallet {wallet} is already registered')
- neuron = cls.get_neuron(wallet=wallet, subtensor=subtensor, netuid=netuid)
- if not refresh_ports:
- port = neuron.axon_info.port
- config.wallet.reregister = False
- else:
- cls.ensure_registration(wallet=wallet,
- subtensor=subtensor,
- netuid=netuid,
- max_fee=max_fee,
- burned_register=burned_register,
- sleep_interval=sleep_interval,
- display_kwargs=kwargs)
- config.logging.debug = debug
-
- wallet = bittensor.wallet(config=config)
- c.print(f'wallet {wallet} is registered')
-
- config.axon.port = cls.resolve_port(port)
- c.print(f'using port {config.axon.port}')
- neuron_class(config=config).run()
-
- @classmethod
- def validator_neuron(cls, mode='core', modality='text.prompting'):
- return c.import_object(f'commune.bittensor.neurons.{modality}.validators.{mode}.neuron.neuron')
- @classmethod
- def validator(cls,
- wallet=f'{default_coldkey}.vali',
- network =default_network,
- netuid=1,
- device = None,
- debug = True,
- remote:bool = True,
- tag=None,
- sleep_interval = 2,
- autocast = True,
- burned_register = False,
- logging:bool = True,
- max_fee = 2.0,
- modality='text.prompting',
- mode = 'relay'
- ):
- kwargs = cls.locals2kwargs(locals())
- c.print(kwargs)
- if tag == None:
- if network in ['local', 'finney']:
- tag = f'{wallet}::finney::{netuid}'
- else:
- tag = f'{wallet}::{network}::{netuid}'
- kwargs['tag'] = tag
- if remote:
- kwargs['remote'] = False
- return cls.remote_fn(fn='validator',name=f'validator::{tag}', kwargs=kwargs)
-
- subtensor = bittensor.subtensor(network=network)
- coldkey, hotkey = wallet.split('.')
- wallet = bittensor.wallet(name=coldkey, hotkey=hotkey)
- bittensor.utils.version_checking()
-
- cls.ensure_registration(wallet=wallet,
- subtensor=subtensor,
- netuid=netuid,
- max_fee=max_fee,
- burned_register=burned_register,
- sleep_interval=sleep_interval,
- display_kwargs=kwargs)
-
- validator_neuron = cls.validator_neuron(mode=mode, modality=modality)
- config = validator_neuron.config()
-
- device = cls.most_free_gpu() if device == None else device
- if not str(device).startswith('cuda:'):
- device = f'cuda:{device}'
- config.neuron.device = device
-
- validator_neuron(config=config,
- wallet=wallet,
- subtensor=subtensor,
- netuid=netuid).run()
-
- @classmethod
- def ensure_registration(cls,
- wallet,
- subtensor =default_network,
- burned_register = False,
- netuid = 3,
- max_fee = 2.0,
- sleep_interval=60,
- display_kwargs=None):
- # wait for registration
- while not cls.is_registered(wallet, subtensor=subtensor, netuid=netuid):
- # burn registration
-
- if burned_register:
- cls.burned_register(
- wallet = wallet,
- netuid = netuid,
- wait_for_inclusion = False,
- wait_for_finalization = True,
- prompt = False,
- subtensor = subtensor,
- max_fee = max_fee,
- )
-
- c.sleep(sleep_interval)
-
- cls.print(f'Pending Registration {wallet} Waiting 2s ...')
- if display_kwargs:
- cls.print(display_kwargs)
- cls.print(f'{wallet} is registered on {subtensor} {netuid}!')
- @classmethod
- def burn_reg_unreged(cls, time_sleep= 10, **kwargs):
- for w in cls.unreged():
- cls.burned_register(w, **kwargs)
-
- @classmethod
- def miner_exists(cls, wallet:str, network:str=default_network, netuid:int=default_netuid):
- miners = cls.miners(network=network, netuid=netuid)
- return wallet in miners
-
- @classmethod
- def fleet(cls,
- name:str=default_coldkey,
- netuid:int= default_netuid,
- network:str=default_network,
- model : str = default_model,
- refresh: bool = True,
- burned_register:bool=False,
- ensure_registration:bool=False,
- device:str = 'cpu',
- max_fee:float=3.5,
- refresh_ports:bool = False,
- hotkeys:List[str] = None,
- remote: bool = False,
- reged : bool = False,
- n:int = 1000):
-
- if remote:
- kwargs = c.localswkwargs(locals())
- kwargs['remote'] = False
- cls.remote_fn('fleet', kwargs=kwargs)
-
- if reged:
- wallets = cls.reged(name)
- else:
- if hotkeys == None:
- wallets = [f'{name}.{h}' for h in cls.hotkeys(name)]
- else:
- wallets = [f'{name}.{h}' for h in hotkeys]
-
-
- subtensor = cls.get_subtensor(network)
-
- avoid_ports = []
- miners = cls.miners(netuid=netuid)
-
- for i, wallet in enumerate(wallets):
- miner_name = cls.get_miner_name(wallet=wallet, network=network, netuid=netuid)
- if cls.miner_exists(wallet, network=network, netuid=netuid) and not refresh:
- cls.print(f'{miner_name} is already running. Skipping ...')
- continue
-
- if miner_name in miners and not refresh:
- cls.print(f'{miner_name} is already running. Skipping ...')
- continue
-
-
- assert cls.wallet_exists(wallet), f'Wallet {wallet} does not exist.'
-
- if cls.is_registered(wallet, subtensor=subtensor, netuid=netuid):
- cls.print(f'{wallet} is already registered on {subtensor} {netuid}!')
- neuron = cls.get_neuron(wallet=wallet, subtensor=subtensor, netuid=netuid)
-
- if refresh_ports:
- axon_port = cls.free_port(reserve=False, avoid_ports=avoid_ports)
- avoid_ports.append(axon_port)
- prometheus_port = axon_port - 1000
- else:
- axon_port = neuron.axon_info.port
- prometheus_port = neuron.prometheus_info.port
- else:
- # ensure registration
- if ensure_registration:
- cls.ensure_registration(wallet,
- subtensor=subtensor,
- netuid=netuid,
- burned_register=burned_register,
- max_fee=max_fee)
- burned_register = False # only burn register for first wallet
- axon_port = cls.free_port(reserve=False, avoid_ports=avoid_ports)
- avoid_ports.append(axon_port)
- prometheus_port = axon_port - 1000
-
-
- avoid_ports += [axon_port, prometheus_port]
- avoid_ports = list(set(avoid_ports)) # avoid duplicates, though htat shouldnt matter
-
-
- cls.print(f'Deploying -> Miner: {miner_name} Device: {device} Axon_port: {axon_port}, Prom_port: {prometheus_port}')
- cls.mine(wallet=wallet,
- remote=True,
- model=model,
- netuid=netuid,
- device=device,
- refresh=refresh,
- port=axon_port,
- network=network,
- miner_name = miner_name,
- prometheus_port = prometheus_port,
- burned_register=burned_register,
- refresh_ports=refresh_ports,
- max_fee=max_fee)
-
- n -= 1
- if n <= 0:
- cls.print('Max miners reached')
- break
-
- @classmethod
- def miners(cls,
- wallet:str=None,
- unreged:bool=False,
- reged:bool=False,
- netuid:int=default_netuid,
- network:str =default_network,
- prefix:str='miner'):
- kwargs = c.locals2kwargs(locals())
- return list(cls.wallet2miner( **kwargs).values())
-
- @classmethod
- def validators(cls, *args, **kwargs):
- return list(cls.wallet2validator(*args, **kwargs).keys())
-
- @classmethod
- def version(cls):
- return c.version('bittensor')
- @classmethod
- def wallet2validator(cls,
- wallet=None,
- unreged=False,
- reged=False,
- netuid=default_netuid,
- network =default_network,
- prefix='validator'):
- network = cls.resolve_network(network)
- wallet2miner = {}
- if unreged:
- filter_wallets = cls.unreged()
- elif reged:
- filter_wallets = cls.reged()
- else:
- filter_wallets = []
-
- for m in cls.pm2_list(prefix):
-
- wallet_name = m.split('::')[1]
- if netuid != None and m.split('::')[-1] != str(netuid):
- continue
- if len(filter_wallets) > 0 and wallet_name not in filter_wallets:
- continue
- wallet2miner[wallet_name] = m
-
- if wallet in wallet2miner:
- return wallet2miner[wallet]
- return wallet2miner
-
-
- @classmethod
- def resolve_network(cls, network):
- if network in ['local']:
- network = 'finney'
- return network
-
- @classmethod
- def wallet2miner(cls,
- wallet=None,
- unreged=False,
- reged=False,
- netuid=default_netuid,
- network =default_network,
- prefix='miner'):
- wallet2miner = {}
- network = cls.resolve_network(network)
- if unreged:
- filter_wallets = cls.unreged()
- elif reged:
- filter_wallets = cls.reged()
- else:
- filter_wallets = []
-
-
- for m in cls.pm2_list(prefix):
-
- wallet_name = m.split('::')[1]
- network_name = m.split('::')[2]
- if netuid != None and m.split('::')[-1] != str(netuid):
- continue
- if len(filter_wallets) > 0 and wallet_name not in filter_wallets:
- continue
- if network != None and network != network_name:
- continue
- wallet2miner[wallet_name] = m
-
- if wallet in wallet2miner:
- return wallet2miner[wallet]
- return wallet2miner
-
-
- w2m = wallet2miner
- @classmethod
- def get_miner(cls, wallet):
- return cls.wallet2miner(wallet)
- @classmethod
- def kill_miners(cls, prefix='miner'):
- return c.kill(prefix)
-
- @classmethod
- def kill(cls, *wallet):
- w2m = cls.wallet2miner()
- for w in wallet:
- if w in w2m:
- cls.print(f'Killing {w}')
- c.kill(w2m[w])
- else:
- cls.print(f'Miner {w} not found.')
-
- @classmethod
- def restart(cls, wallet):
- return c.restart(cls.w2m(wallet))
- @classmethod
- def block(cls, subtensor=default_network):
- subtensor = cls.get_subtensor(subtensor)
- return subtensor.get_current_block()
-
- @classmethod
- def burn_fee(cls, subtensor='finney', netuid=default_netuid):
- subtensor = cls.get_subtensor(subtensor)
- return subtensor.query_subtensor('Burn', None, [netuid]).value/1e9
- @classmethod
- def query_map(cls, key='Uids', subtensor='finney', netuid=default_netuid):
- subtensor = cls.get_subtensor(subtensor)
- return subtensor.query_map_subtensor(key, None, [netuid]).records
-
-
-
- @classmethod
- def key2uid(cls, netuid:int=default_netuid):
- uids = cls.query_map('Uids', netuid=netuid)[:10]
- keys = {k.value:v.value for k,v in uids}
- return uids
-
-
- @classmethod
- def logs(cls, wallet, **kwargs):
- return c.logs(cls.wallet2miner(**kwargs).get(wallet), mode='local', start_line=-10, end_line=-1)
-
- @classmethod
- async def async_logs(cls, wallet, network=default_network, netuid=3):
- processes = c.pm2ls(wallet)
- logs_dict = {}
- for p in processes:
- if any([p.startswith(k) for k in ['miner', 'validator'] ]):
- logs_dict[p.split('::')[0]] = c.logs(p, mode='local')
-
- if len(logs_dict) == 1:
- return list(logs_dict.values())[0]
-
- return logs_dict
-
- @classmethod
- def miner2logs(cls,
- network=default_network,
- netuid=1,
- verbose:bool = True):
-
- miners = cls.miners()
- miner2logs = {}
- for miner in miners:
- miner2logs[miner] = c.pm2_logs(miner, end_line=200, mode='local')
-
-
- if verbose:
- for miner, logs in miner2logs.items():
- pad = 100*'-'
- color = cls.random_color()
- cls.print(pad,f'\n{miner}\n', pad, color=color)
- cls.print( logs, '\n\n', color=color)
-
- # return miner2logs
-
-
- check_miners = miner2logs
-
- @classmethod
- def unstake_coldkey(cls,
- coldkey = default_coldkey,
- wait_for_inclusion = True,
- wait_for_finalization = False,
- prompt = False,
- subtensor = None,
- min_stake = 0.1
- ):
-
- for wallet in cls.wallets(coldkey, registered=True):
- cls.print(f'Unstaking {wallet} ...')
- stake = cls.get_stake(wallet)
- if stake >= min_stake:
- cls.print(f'Unstaking {wallet} Stake/MinStake ({stake}>{min_stake})')
- amount_unstaked = cls.unstake(wallet=wallet,
- wait_for_inclusion=True,
- wait_for_finalization=wait_for_finalization,
- prompt=prompt,
- subtensor=subtensor)
- else:
- cls.print(f'Not enough stake {stake} to unstake {wallet}, min_stake: {min_stake}')
-
- unstake_ck = unstake_coldkey
-
-
- @classmethod
- def set_pool_address(cls, pool_address):
- cls.putc('pool_address', pool_address)
- cls.print(f'Set pool address to {pool_address}')
-
- @classmethod
- def set_coldkey(cls, coldkey):
- return cls.putc('coldkey', coldkey)
-
- @classmethod
- def pool_address(cls):
- return cls.getc('pool_address', cls.default_pool_address)
-
- @classmethod
- def unstake2pool(cls,
- pool_address:str = None,
- coldkey:str = default_coldkey,
- loops = 20,
- transfer: bool = True,
- min_balance: float = 0.1,
- min_stake: float = 0.1,
- remote = True,
- sleep = 1,
-
- ):
-
- if remote:
- kwargs = cls.locals2kwargs(locals())
- kwargs['remote'] = False
- return cls.remote_fn(fn='unstake2pool',name=f'bt::unstake2pool', kwargs=kwargs)
-
- if pool_address == None:
- pool_address = cls.pool_address()
- for i in range(loops):
-
-
- cls.print(f'-YOOO- Unstaking {coldkey}')
-
-
- cls.unstake_coldkey(coldkey=coldkey, min_stake=min_stake) # unstake all wallets
-
- if pool_address == cls.address(coldkey):
- cls.print(f'Coldkey {coldkey} is equal to {pool_address}, skipping transfer')
- else:
- cls.transfer(dest=pool_address, amount=-1, wallet=coldkey, min_balance=min_balance)
-
-
- cls.sleep(sleep)
-
-
-
-
-
-
- @classmethod
- def unstake(
- cls,
- wallet ,
- amount: float = None ,
- wait_for_inclusion:bool = True,
- wait_for_finalization:bool = False,
- prompt: bool = False,
- subtensor: 'bittensor.subtensor' = None,
- ) -> bool:
- """ Removes stake into the wallet coldkey from the specified hotkey uid."""
- subtensor = cls.get_subtensor(subtensor)
- wallet = cls.get_wallet(wallet)
-
- return subtensor.unstake( wallet=wallet,
- hotkey_ss58=wallet.hotkey.ss58_address,
- amount=amount,
- wait_for_inclusion=wait_for_inclusion,
- wait_for_finalization=wait_for_finalization,
- prompt=prompt )
-
- @classmethod
- def sand(cls, ratio=1.0, model=default_model ):
- reged = cls.reged()
- reged = reged[:int(len(reged)*ratio)]
- for wallet in reged:
- cls.mine(wallet, model=model)
-
- @classmethod
- def allinone(cls, overwrite_keys=False, refresh_miners=False, refresh_servers= False):
- cls.add_keys(overwrite=overwrite_keys) # add keys job
- cls.add_servers(refresh=refresh_servers) # add servers job
- cls.fleet(refresh=refresh_miners) # fleet job
- cls.unstake2pool() # unstake2pool job
- @classmethod
- def mems(cls,
- coldkey:str=default_coldkey,
- reged : bool = False,
- unreged:bool = False,
- miners_only:bool = False,
- no_miners: bool = False,
- path:str = None,
- network:str = default_network,
- netuid:int=default_netuid):
- if reged:
- hotkeys = cls.registered_hotkeys(coldkey, netuid=netuid)
- unreged = False
- elif unreged:
- hotkeys = cls.unregistered_hotkeys(coldkey, netuid=netuid)
- else:
- hotkeys = cls.hotkeys(coldkey)
-
- wallets = [cls.wallet_json(f'{coldkey}.{hotkey}' ) for hotkey in hotkeys]
- wallets = [w for w in wallets if w != None]
-
-
- hotkey_map = {hotkeys[i]: w['secretPhrase'] for i, w in enumerate(wallets)}
-
- coldkey_json = cls.coldkeypub_json(coldkey)
-
- if 'ss58Address' not in coldkey_json:
- coldkey_json = cls.coldkey_json(coldkey)
-
-
- coldkey_info = [f"btcli regen_coldkeypub --ss58 {coldkey_json['ss58Address']} --wallet.name {coldkey}"]
-
-
- if miners_only or no_miners:
- miners = cls.miners(netuid=netuid, network=network, reged=reged)
- c.print()
-
- if no_miners:
- assert miners_only == False
- if miners_only:
- assert no_miners == False
-
-
-
- template = 'btcli regen_hotkey --wallet.name {coldkey} --wallet.hotkey {hotkey} --mnemonic {mnemonic}'
- for hk, hk_mnemonic in hotkey_map.items():
- wallet = f'{coldkey}.{hk}'
-
- if miners_only:
- if wallet not in miners :
- continue
-
- if no_miners:
- if wallet in miners :
- continue
- info = template.format(mnemonic=hk_mnemonic, coldkey=coldkey, hotkey=hk)
-
- coldkey_info.append(info)
-
- coldkey_info_text = '\n'.join(coldkey_info)
- if path is not None:
- cls.put_text(path, coldkey_info_text)
- # return coldkey_info
-
- return coldkey_info_text
-
-
- @classmethod
- def wallet_json(cls, wallet):
- path = cls.get_wallet_path(wallet)
- return cls.get_json(path)
-
-
- @classmethod
- def coldkey_json(cls, coldkey=default_coldkey):
- path = cls.coldkey_path(coldkey)
- coldkey_json = cls.get_json(path, None)
- if coldkey_json is None:
- coldkey_json = cls.coldkeypub_json(coldkey)
- return coldkey_json
-
- @classmethod
- def hotkey_json(cls, hotkey, coldkey=default_coldkey):
- path = cls.hotkey_path(hotkey, coldkey)
- coldkey_json = cls.get_json(path, {})
- return coldkey_json
-
-
-
- @classmethod
- def coldkeypub_json(cls, coldkey):
- path = cls.coldkeypub_path(coldkey)
- return cls.get_json(path)
-
-
- @classmethod
- def servers_online(cls):
- return
-
- servers = servers_online
- @classmethod
- def servers(cls, **kwargs):
-
- return c.servers('server')
-
- @classmethod
- def wallet_json(cls, wallet):
- path = cls.get_wallet_path(wallet)
- return cls.get_json(path)
-
-
-
- @classmethod
- def get_top_uids(cls, k:int=100,
- netuid=None,
- subtensor=None,
- metagraph=None,
- return_dict=True,
- **kwargs):
-
- if metagraph == None:
- metagraph = cls.get_metagraph(netuid=netuid, subtensor=subtensor, **kwargs)
-
- sorted_indices = torch.argsort(metagraph.incentive, descending=True)
- top_uids = sorted_indices[:k]
- if return_dict:
-
- top_uids = {uid: metagraph.incentive[uid].item() for i, uid in enumerate(top_uids.tolist())}
-
- return top_uids
-
- def top_uids(self,k=10):
- self.get_top_uids(metagraph=self.metagraph,k=k)
- def incentive(self ):
- return self.metagraph.incentive.data
- def uids(self):
- return self.metagraph.uids.data
- def dividends(self):
- return self.metagraph.dividends.data
-
- @classmethod
- def start_node(cls, mode='docker', sudo=True):
- if mode == 'docker':
- return cls.cmd('docker-compose up -d', cwd=cls.chain_repo, verbose=True, sudo=sudo)
- else:
- raise NotImplementedError('Only docker mode is supported at this time.')
-
- @classmethod
- def node_logs(cls, mode='docker', sudo=True):
- if mode == 'docker':
- return cls.cmd('docker ps', cwd=cls.chain_repo, verbose=False, sudo=sudo)
- else:
- raise NotImplementedError('Only docker mode is supported at this time.')
-
-
-
- @classmethod
- def redeploy_zero_miners(cls, netuid=11, coldkey=default_coldkey, **kwargs):
- zero_miners = cls.zero_emission_miners(coldkey=coldkey, netuid=netuid)
- hotkeys = [int(m.split('.')[-1]) for m in zero_miners]
- cls.fleet(
- hotkeys=hotkeys,
- refresh=True,
- refresh_ports=True,
- netuid=netuid,
-
- **kwargs)
-
-
-
-
- @classmethod
- def num_miners(cls,**kwargs):
- return len(cls.miners(**kwargs))
-
- n_miners = num_miners
-
- @classmethod
- def watchdog(cls,
- sync_interval:int=5,
- print_interval:int = 10,
- remote:bool=True):
- if remote:
- kwargs = c.locals2kwargs(locals())
- kwargs['remote'] = False
- return cls.remote_fn('watchdog', kwargs=kwargs)
-
- self = cls()
- time_start = c.time()
- time_elapsed = 0
- counts = { 'save':0}
- while True:
- time_elapsed = c.time() - time_start
-
- if time_elapsed % sync_interval == 0:
- self.sync()
- counts['sync'] += 1
- if time_elapsed % print_interval == 0:
- c.log(f"Watchdog: {time_elapsed} seconds elapsed COUNTS ->S {counts}")
-
-
- _reged_wallets = None
-
- def talk(self,
- prompt:str = 'what is the whether',
- role:str='assistant',
- timeout:int=4,
- n:int=10,
- trials:int=3,
- n_jobs:int = 2,
- **kwargs):
- assert trials > 0, 'trials must be greater than 0'
- if self._reged_wallets == None:
- reged = self.reged()
- self._reged_wallets = [self.get_wallet(r) for r in reged]
- assert len(self._reged_wallets) > 0, 'No registered wallets found'
- wallet = c.choice(self._reged_wallets)
- d = bittensor.text_prompting_pool(keypair=wallet.hotkey, metagraph=self.metagraph)
- uids = c.shuffle(list(range(self.metagraph.n)))[:n]
-
- jobs = [d.async_forward(roles=[role], messages=[prompt], timeout=timeout, uids=uids) for i in range(n_jobs)]
- response = []
- for r in c.gather(jobs):
- response.extend(r)
-
- success_responses = [r.completion.strip() for r in response if r.return_code == 1]
- if len(success_responses) == 0:
- c.print(f'No successful responses for prompt {prompt} role {role} timeout {timeout} n {n}')
- return self.talk(prompt=prompt, role=role, timeout=timeout, n=n, trials=trials-1, **kwargs)
- return success_responses[0]
-
-
- @classmethod
- def model_fleet(cls, n=20):
- free_ports = c.free_ports(n=n)
- for i in range(n):
- cls.serve( name=f'model.bt.{i}', port=free_ports[i])
-
-
-
-
-
diff --git a/commune/modules/bittensor/bittensor_module.yaml b/commune/modules/bittensor/bittensor_module.yaml
deleted file mode 100644
index 363b387fb..000000000
--- a/commune/modules/bittensor/bittensor_module.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-coldkey: alice
-module: BittensorModule
-netuid: 11
-network: finney
-network2endpoint:
- finney: wss://entrypoint-finney.opentensor.ai:443
- local: ws://0.0.0.0:9944
- test: wss://test.finney.opentensor.ai:443
-pool_address: null
-model: textgen
-neurons:
- openai: commune.modules.bittensor.neurons.text.prompting.miners.openai.neuron.OpenAIMiner
- openai.free: commune.modules.bittensor.neurons.text.prompting.miners.openai_freew.neuron.OpenAIFreeMiner
- commune: commune.modules.bittensor.neurons.text.prompting.miners.commune.neuron.MaoMiner
- textgen: commune.modules.bittensor.neurons.text.prompting.miners.textgen.neuron.TextgenMiner
\ No newline at end of file
diff --git a/commune/modules/bittensor/dashboard.py b/commune/modules/bittensor/dashboard.py
deleted file mode 100644
index c57cd1d32..000000000
--- a/commune/modules/bittensor/dashboard.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import streamlit as st
-import torch
-import os,sys
-import asyncio
-from transformers import AutoConfig
-asyncio.set_event_loop(asyncio.new_event_loop())
-import bittensor
-from typing import List, Union, Optional, Dict
-from munch import Munch
-
-class Dashboard(commune.Module):
-
- def __init__(self,
- wallet:Union[bittensor.wallet, str] = None,
- subtensor: Union[bittensor.subtensor, str] = 'local',
- ):
-
- self.set_subtensor(subtensor=subtensor)
- self.set_wallet(wallet=wallet)
-
- @property
- def network_options(self):
- return ['finney','nakamoto', 'local', 'nobunaga', '0.0.0.0:9944']
-
- @property
- def chain_endpoint_options(self):
- return ['0.0.0.0:9944']
-
- def set_subtensor(self, subtensor=None):
- if isinstance(subtensor, str):
- if subtensor in self.network_options:
- subtensor = bittensor.subtensor(network=subtensor)
- elif ':' in subtensor:
- subtensor = bittensor.subtensor(chain_endpoint=subtensor)
-
- self.subtensor = subtensor if subtensor else bittensor.subtensor()
- self.metagraph = bittensor.metagraph(subtensor=self.subtensor).load()
-
- return self.subtensor
-
- def set_wallet(self, wallet=None)-> bittensor.wallet:
- if isinstance(wallet, str):
- name, hotkey = wallet.split('.')
- wallet =bittensor.wallet(name=name, hotkey=hotkey)
-
- self.wallet = wallet if wallet else bittensor.wallet()
- return self.wallet
-
- @property
- def neuron(self):
- return self.wallet.get_neuron(subtensor=self.subtensor)
-
-
- def list_wallets(self, registered=True, unregistered=True):
- wallet_paths = self.list_wallet_paths()
- wallet_path = os.path.expanduser(self.wallet.config.wallet.path)
-
- wallets = [p.replace(wallet_path, '').replace('/hotkeys/','.') for p in wallet_paths]
-
-
- return wallets
-
-
-
- @property
- def network(self):
- return self.subtensor.network
-
-
- @property
- def is_registered(self):
- return self.wallet.is_registered(subtensor= self.subtensor)
-
-
- def sync(self):
- return self.metagraph.sync()
-
-
- # Streamlit Landing Page
- selected_wallets = []
- def streamlit_sidebar(self):
- wallets_list = self.list_wallets()
- wallet = st.selectbox(f'Select Wallets ({wallets_list[0]})', wallets_list, 0)
- self.set_wallet(wallet)
-
- network_options = self.network_options
- network = st.selectbox(f'Select Network ({network_options[0]})', self.network_options, 0)
- self.set_subtensor(subtensor=network)
-
- sync_network = st.button('Sync the Network')
- if sync_network:
- self.sync()
-
- def streamlit_neuron_metrics(self, num_columns=3):
- with st.expander('Neuron Stats', True):
- cols = st.columns(num_columns)
- if self.is_registered:
- neuron = self.neuron
- for i, (k,v) in enumerate(neuron.__dict__.items()):
-
- if type(v) in [int, float]:
- cols[i % num_columns].metric(label=k, value=v)
- st.write(neuron.__dict__)
- else:
- st.write(f'## {self.wallet} is not Registered on {self.subtensor.network}')
-
- @classmethod
- def streamlit(cls):
- st.set_page_config(layout="wide")
- self = cls(wallet='fish.1', subtensor='nobunaga')
-
- with st.sidebar:
- self.streamlit_sidebar()
-
-
- st.write(f'# BITTENSOR DASHBOARD {self.network}')
-
- self.streamlit_neuron_metrics()
-
-
-
-if __name__ == "__main__":
- Dashboard.streamlit()
-
-
-
-
-
-
diff --git a/commune/modules/bittensor/example/register_wallet_example.py b/commune/modules/bittensor/example/register_wallet_example.py
deleted file mode 100644
index 546352518..000000000
--- a/commune/modules/bittensor/example/register_wallet_example.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import commune
-wallet = f"{coldkey}.{hotkey}"
-
-module = commune.get_commune('bittensor')
-moduel(wallet=wallet).register(dev_ids = [0,1,2])
\ No newline at end of file
diff --git a/commune/modules/bittensor/keyfile/__init__.py b/commune/modules/bittensor/keyfile/__init__.py
deleted file mode 100644
index 7b8a3ca6d..000000000
--- a/commune/modules/bittensor/keyfile/__init__.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-from . import keyfile_impl
-
-class keyfile (object):
- """ Factory for a bittensor on device keypair
- """
- def __new__(
- cls,
- path: str = None,
- _mock: bool = False
- ) -> 'bittensor.Keyfile':
- r""" Initialize a bittensor on device keypair interface.
-
- Args:
- path (required=False, default: ~/.bittensor/wallets/default/coldkey ):
- Path where this keypair is stored.
- """
- path = '~/.bittensor/wallets/default/coldkey' if path == None else path
- if _mock:
- return keyfile_impl.MockKeyfile( path = path )
- else:
- return keyfile_impl.Keyfile( path = path )
-
- @classmethod
- def mock(cls):
- return keyfile(_mock=True)
diff --git a/commune/modules/bittensor/keyfile/keyfile_impl.py b/commune/modules/bittensor/keyfile/keyfile_impl.py
deleted file mode 100644
index 80168e39b..000000000
--- a/commune/modules/bittensor/keyfile/keyfile_impl.py
+++ /dev/null
@@ -1,556 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import os
-import base64
-import json
-import stat
-import getpass
-import bittensor
-from typing import Optional
-from pathlib import Path
-
-from ansible_vault import Vault
-from cryptography.exceptions import InvalidSignature, InvalidKey
-from cryptography.fernet import Fernet, InvalidToken
-from cryptography.hazmat.primitives import hashes
-from cryptography.hazmat.backends import default_backend
-from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
-from password_strength import PasswordPolicy
-from substrateinterface.utils.ss58 import ss58_encode, ss58_decode
-from termcolor import colored
-
-class KeyFileError(Exception):
- """ Error thrown when the keyfile is corrupt, non-writable, nno-readable or the password used to decrypt is invalid.
- """
-
-def serialized_keypair_to_keyfile_data( keypair: 'bittensor.Keypair' ):
- """ Serializes keypair object into keyfile data.
- Args:
- password ( str, required ):
- password to verify.
- Returns:
- valid ( bool ):
- True if the password meets validity requirements.
- """
- seed_hex = keypair.seed_hex
- if seed_hex != None:
- if isinstance(seed_hex, bytes ):
- seed_hex = str(keypair.seed_hex)[2:-1]
-
-
- json_data = {
- 'accountId': "0x" + keypair.public_key.hex() if keypair.public_key != None else None,
- 'publicKey': "0x" + keypair.public_key.hex() if keypair.public_key != None else None,
- 'secretPhrase': keypair.mnemonic if keypair.mnemonic != None else None,
- 'secretSeed': "0x" + seed_hex if seed_hex != None else None,
- 'ss58Address': keypair.ss58_address if keypair.ss58_address != None else None
- }
- data = json.dumps( json_data ).encode()
- return data
-
-def deserialize_keypair_from_keyfile_data( keyfile_data:bytes ) -> 'bittensor.Keypair':
- """ Deserializes Keypair object from passed keyfile data.
- Args:
- keyfile_data ( bytest, required ):
- Keyfile data as bytes to be loaded.
- Returns:
- keypair (bittensor.Keypair):
- Keypair loaded from bytes.
- Raises:
- KeyFileError:
- Raised if the passed bytest cannot construct a keypair object.
- """
- # Decode from json.
- keyfile_data = keyfile_data.decode()
- try:
- keyfile_dict = dict(json.loads( keyfile_data ))
- except:
- string_value = str(keyfile_data)
- if string_value[:2] == "0x":
- string_value = ss58_encode( string_value )
- keyfile_dict = {
- 'accountId': None,
- 'publicKey': None,
- 'secretPhrase': None,
- 'secretSeed': None,
- 'ss58Address': string_value
- }
- else:
- raise KeyFileError('Keypair could not be created from keyfile data: {}'.format( string_value ))
-
- if "secretSeed" in keyfile_dict and keyfile_dict['secretSeed'] != None:
- return bittensor.Keypair.create_from_seed(keyfile_dict['secretSeed'])
-
- if "secretPhrase" in keyfile_dict and keyfile_dict['secretPhrase'] != None:
- return bittensor.Keypair.create_from_mnemonic(mnemonic=keyfile_dict['secretPhrase'])
-
- if "ss58Address" in keyfile_dict and keyfile_dict['ss58Address'] != None:
- return bittensor.Keypair( ss58_address = keyfile_dict['ss58Address'] )
-
- else:
- raise KeyFileError('Keypair could not be created from keyfile data: {}'.format( keyfile_dict ))
-
-def validate_password( password:str ) -> bool:
- """ Validates the password again a password policy.
- Args:
- password ( str, required ):
- password to verify.
- Returns:
- valid ( bool ):
- True if the password meets validity requirements.
- """
- policy = PasswordPolicy.from_names(
- strength=0.20,
- entropybits=10,
- length=6,
- )
- if not password:
- return False
- tested_pass = policy.password(password)
- result = tested_pass.test()
- if len(result) > 0:
- print(colored('Password not strong enough. Try increasing the length of the password or the password complexity'))
- return False
- password_verification = getpass.getpass("Retype your password: ")
- if password != password_verification:
- print("Passwords do not match")
- return False
- return True
-
-def ask_password_to_encrypt() -> str:
- """ Password from user prompt.
- Returns:
- password (str):
- Valid password from user prompt.
- """
- valid = False
- while not valid:
- password = getpass.getpass("Specify password for key encryption: ")
- valid = validate_password(password)
- return password
-
-def keyfile_data_is_encrypted_ansible( keyfile_data:bytes ) -> bool:
- """ Returns true if the keyfile data is ansible encrypted.
- Args:
- keyfile_data ( bytes, required ):
- Bytes to validate
- Returns:
- is_ansible (bool):
- True if data is ansible encrypted.
- """
- return keyfile_data[:14] == b'$ANSIBLE_VAULT'
-
-def keyfile_data_is_encrypted_legacy( keyfile_data:bytes ) -> bool:
- """ Returns true if the keyfile data is legacy encrypted.
- Args:
- keyfile_data ( bytes, required ):
- Bytes to validate
- Returns:
- is_legacy (bool):
- True if data is legacy encrypted.
- """
- return keyfile_data[:6] == b"gAAAAA"
-
-def keyfile_data_is_encrypted( keyfile_data:bytes ) -> bool:
- """ Returns true if the keyfile data is encrypted.
- Args:
- keyfile_data ( bytes, required ):
- Bytes to validate
- Returns:
- is_encrypted (bool):
- True if data is encrypted.
- """
- return keyfile_data_is_encrypted_ansible( keyfile_data ) or keyfile_data_is_encrypted_legacy( keyfile_data )
-
-def encrypt_keyfile_data ( keyfile_data:bytes, password: str = None ) -> bytes:
- """ Encrypts passed keyfile data using ansible vault.
- Args:
- keyfile_data ( bytes, required ):
- Bytes to validate
- password ( bool, optional ):
- It set, uses this password to encrypt data.
- Returns:
- encrytped_data (bytes):
- Ansible encrypted data.
- """
- password = ask_password_to_encrypt() if password == None else password
- console = bittensor.__console__;
- with console.status(":locked_with_key: Encrypting key..."):
- vault = Vault( password )
- return vault.vault.encrypt ( keyfile_data )
-
-
-def get_coldkey_password_from_environment(coldkey_name: str) -> Optional[str]:
-
- for env_var in os.environ:
- if (
- env_var.upper().startswith("BT_COLD_PW_")
- and env_var.upper().endswith(coldkey_name.upper())
- ):
- return os.getenv(env_var)
-
- return None
-
-
-def decrypt_keyfile_data(keyfile_data: bytes, password: str = None, coldkey_name: Optional[str] = None) -> bytes:
- """ Decrypts passed keyfile data using ansible vault.
- Args:
- keyfile_data ( bytes, required ):
- Bytes to validate
- password ( bool, optional ):
- It set, uses this password to decrypt data.
- Returns:
- decrypted_data (bytes):
- Decrypted data.
- Raises:
- KeyFileError:
- Raised if the file is corrupted or if the password is incorrect.
- """
- if coldkey_name is not None and password is None:
- password = get_coldkey_password_from_environment(coldkey_name)
-
- try:
- password = getpass.getpass("Enter password to unlock key: ") if password is None else password
- console = bittensor.__console__;
- with console.status(":key: Decrypting key..."):
- # Ansible decrypt.
- if keyfile_data_is_encrypted_ansible( keyfile_data ):
- vault = Vault( password )
- decrypted_keyfile_data = vault.load( keyfile_data )
- # Legacy decrypt.
- elif keyfile_data_is_encrypted_legacy( keyfile_data ):
- __SALT = b"Iguesscyborgslikemyselfhaveatendencytobeparanoidaboutourorigins"
- kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), salt=__SALT, length=32, iterations=10000000, backend=default_backend())
- key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
- cipher_suite = Fernet(key)
- decrypted_keyfile_data = cipher_suite.decrypt( keyfile_data )
- # Unknown.
- else:
- raise KeyFileError( "Keyfile data: {} is corrupt".format( keyfile_data ))
-
- except (InvalidSignature, InvalidKey, InvalidToken):
- raise KeyFileError('Invalid password')
-
- if not isinstance(decrypted_keyfile_data, bytes):
- decrypted_keyfile_data = json.dumps( decrypted_keyfile_data ).encode()
- return decrypted_keyfile_data
-
-class Keyfile( object ):
- """ Defines an interface for a subtrate interface keypair stored on device.
- """
- def __init__( self, path: str ):
- self.path = os.path.expanduser(path)
- self.name = Path(self.path).parent.stem
-
- def __str__(self):
- if not self.exists_on_device():
- return "Keyfile (empty, {})>".format( self.path )
- if self.is_encrypted():
- return "Keyfile (encrypted, {})>".format( self.path )
- else:
- return "Keyfile (decrypted, {})>".format( self.path )
-
- def __repr__(self):
- return self.__str__()
-
- @property
- def keypair( self ) -> 'bittensor.Keypair':
- """ Returns the keypair from path, decrypts data if the file is encrypted.
- Args:
- password ( str, optional ):
- Optional password used to decrypt file. If None, asks for user input.
- Returns:
- keypair (bittensor.Keypair):
- Keypair stored under path.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, writable
- corrupted, or if the password is incorrect.
- """
- return self.get_keypair()
-
- @property
- def data( self ) -> bytes:
- """ Returns keyfile data under path.
- Returns:
- keyfile_data (bytes):
- Keyfile data stored under path.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, or writable.
- """
- return self._read_keyfile_data_from_file()
-
- @property
- def keyfile_data( self ) -> bytes:
- """ Returns keyfile data under path.
- Returns:
- keyfile_data (bytes):
- Keyfile data stored under path.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, or writable.
- """
- return self._read_keyfile_data_from_file()
-
- def set_keypair ( self, keypair: 'bittensor.Keypair', encrypt: bool = True, overwrite: bool = False, password:str = None):
- """ Writes the keypair to the file and optional encrypts data.
- Args:
- keypair (bittensor.Keypair):
- Keypair to store under path.
- encrypt ( bool, optional, default = True ):
- If True, encrypts file under path.
- overwrite ( bool, optional, default = True ):
- If True, forces overwrite of current file.
- password ( str, optional ):
- Optional password used to encrypt file. If None, asks for user input.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, or writable.
- """
- self.make_dirs()
- keyfile_data = serialized_keypair_to_keyfile_data( keypair )
- if encrypt:
- keyfile_data = encrypt_keyfile_data( keyfile_data, password )
- self._write_keyfile_data_to_file( keyfile_data, overwrite = overwrite )
-
- def get_keypair(self, password: str = None) -> 'bittensor.Keypair':
- """ Returns the keypair from path, decrypts data if the file is encrypted.
- Args:
- password ( str, optional ):
- Optional password used to decrypt file. If None, asks for user input.
- Returns:
- keypair (bittensor.Keypair):
- Keypair stored under path.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, writable
- corrupted, or if the password is incorrect.
- """
- keyfile_data = self._read_keyfile_data_from_file()
- if keyfile_data_is_encrypted( keyfile_data ):
- keyfile_data = decrypt_keyfile_data(keyfile_data, password, coldkey_name=self.name)
- return deserialize_keypair_from_keyfile_data( keyfile_data )
-
- def make_dirs( self ):
- """ Makes directories for path.
- """
- directory = os.path.dirname( self.path )
- if not os.path.exists( directory ):
- os.makedirs( directory )
-
- def exists_on_device( self ) -> bool:
- """ Returns true if the file exists on the device.
- Returns:
- on_device (bool):
- True if the file is on device.
- """
- if not os.path.isfile( self.path ):
- return False
- return True
-
- def is_readable( self ) -> bool:
- """ Returns true if the file under path is readable.
- Returns:
- readable (bool):
- True if the file is readable.
- """
- if not self.exists_on_device():
- return False
- if not os.access( self.path , os.R_OK ):
- return False
- return True
-
- def is_writable( self ) -> bool:
- """ Returns true if the file under path is writable.
- Returns:
- writable (bool):
- True if the file is writable.
- """
- if os.access(self.path, os.W_OK):
- return True
- return False
-
- def is_encrypted ( self ) -> bool:
- """ Returns true if the file under path is encrypted.
- Returns:
- encrypted (bool):
- True if the file is encrypted.
- """
- if not self.exists_on_device():
- return False
- if not self.is_readable():
- return False
- return keyfile_data_is_encrypted( self._read_keyfile_data_from_file() )
-
- def _may_overwrite ( self ) -> bool:
- choice = input("File {} already exists. Overwrite ? (y/N) ".format( self.path ))
- return choice == 'y'
-
- def encrypt( self, password: str = None):
- """ Encrypts file under path.
- Args:
- password: (str, optional):
- Optional password for encryption. Otherwise asks for user input.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, writable.
- """
- if not self.exists_on_device():
- raise KeyFileError( "Keyfile at: {} is not a file".format( self.path ))
- if not self.is_readable():
- raise KeyFileError( "Keyfile at: {} is not readable".format( self.path ))
- if not self.is_writable():
- raise KeyFileError( "Keyfile at: {} is not writeable".format( self.path ) )
- keyfile_data = self._read_keyfile_data_from_file()
- if not keyfile_data_is_encrypted( keyfile_data ):
- as_keypair = deserialize_keypair_from_keyfile_data( keyfile_data )
- keyfile_data = serialized_keypair_to_keyfile_data( as_keypair )
- keyfile_data = encrypt_keyfile_data( keyfile_data, password )
- self._write_keyfile_data_to_file( keyfile_data, overwrite = True )
-
- def decrypt( self, password: str = None):
- """ Decrypts file under path.
- Args:
- password: (str, optional):
- Optional password for decryption. Otherwise asks for user input.
- Raises:
- KeyFileError:
- Raised if the file does not exists, is not readable, writable
- corrupted, or if the password is incorrect.
- """
- if not self.exists_on_device():
- raise KeyFileError( "Keyfile at: {} is not a file".format( self.path ))
- if not self.is_readable():
- raise KeyFileError( "Keyfile at: {} is not readable".format( self.path ))
- if not self.is_writable():
- raise KeyFileError( "No write access for {}".format( self.path ) )
- keyfile_data = self._read_keyfile_data_from_file()
- if keyfile_data_is_encrypted( keyfile_data ):
- keyfile_data = decrypt_keyfile_data(keyfile_data, password, coldkey_name=self.name)
- as_keypair = deserialize_keypair_from_keyfile_data( keyfile_data )
- keyfile_data = serialized_keypair_to_keyfile_data( as_keypair )
- self._write_keyfile_data_to_file( keyfile_data, overwrite = True )
-
- def _read_keyfile_data_from_file ( self ) -> bytes:
- """ Reads keyfile data from path.
- Returns:
- keyfile_data: (bytes, required):
- Keyfile data sotred under path.
- Raises:
- KeyFileError:
- Raised if the file does not exists or is not readable.
- """
- if not self.exists_on_device():
- raise KeyFileError( "Keyfile at: {} is not a file".format( self.path ))
- if not self.is_readable():
- raise KeyFileError( "Keyfile at: {} is not readable".format( self.path ))
- with open( self.path , 'rb') as file:
- data = file.read()
- return data
-
- def _write_keyfile_data_to_file ( self, keyfile_data:bytes, overwrite: bool = False ):
- """ Writes the keyfile data to path, if overwrite is true, forces operation without asking.
- Args:
- keyfile_data: (bytes, required):
- Byte data to store under path.
- overwrite (bool, optional):
- If True, overwrites data without asking for overwrite permissions from the user.
- Raises:
- KeyFileError:
- Raised if the file is not writable or the user returns No to overwrite prompt.
- """
- # Check overwrite.
- if self.exists_on_device() and not overwrite:
- if not self._may_overwrite():
- raise KeyFileError( "Keyfile at: {} is not writeable".format( self.path ) )
- with open(self.path, "wb") as keyfile:
- keyfile.write( keyfile_data )
- # Set file permissions.
- os.chmod(self.path, stat.S_IRUSR | stat.S_IWUSR)
-
-
-class MockKeyfile( object ):
- """ Defines an interface to a mocked keyfile object (nothing is created on device) keypair is treated as non encrypted and the data is just the string version.
- """
- def __init__( self, path: str ):
- self.path = os.path.expanduser(path)
- self._mock_keypair = bittensor.Keypair.create_from_mnemonic( mnemonic = 'arrive produce someone view end scout bargain coil slight festival excess struggle' )
- self._mock_data = serialized_keypair_to_keyfile_data( self._mock_keypair )
-
- def __str__(self):
- if not self.exists_on_device():
- return "Keyfile (empty, {})>".format( self.path )
- if self.is_encrypted():
- return "Keyfile (encrypted, {})>".format( self.path )
- else:
- return "Keyfile (decrypted, {})>".format( self.path )
-
- def __repr__(self):
- return self.__str__()
-
- @property
- def keypair( self ) -> 'bittensor.Keypair':
- return self._mock_keypair
-
- @property
- def data( self ) -> bytes:
- return bytes(self._mock_data)
-
- @property
- def keyfile_data( self ) -> bytes:
- return bytes( self._mock_data)
-
- def set_keypair ( self, keypair: 'bittensor.Keypair', encrypt: bool = True, overwrite: bool = False, password:str = None):
- self._mock_keypair = keypair
- self._mock_data = serialized_keypair_to_keyfile_data( self._mock_keypair )
-
- def get_keypair(self, password: str = None) -> 'bittensor.Keypair':
- return self._mock_keypair
-
- def make_dirs( self ):
- return
-
- def exists_on_device( self ) -> bool:
- return True
-
- def is_readable( self ) -> bool:
- return True
-
- def is_writable( self ) -> bool:
- return True
-
- def is_encrypted ( self ) -> bool:
- return False
-
- def encrypt( self, password: str = None):
- raise ValueError('Cannot encrypt a mock keyfile')
-
- def decrypt( self, password: str = None):
- return
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/commune/modules/bittensor/miner.py b/commune/modules/bittensor/miner.py
deleted file mode 100644
index 49b833cbf..000000000
--- a/commune/modules/bittensor/miner.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import bittensor
-if __name__ == "__main__":
- template = bittensor.neurons.core_server.neuron().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/miner/neuron.py b/commune/modules/bittensor/miner/neuron.py
deleted file mode 100644
index 5f994bf2f..000000000
--- a/commune/modules/bittensor/miner/neuron.py
+++ /dev/null
@@ -1,711 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-""" Template server.
-
-Example:
- $ import neurons
- $ neurons.text.core_server.neuron().run()
-"""
-
-import bittensor
-import os
-import sys
-
-from .server import server
-from prometheus_client import Counter, Gauge, Histogram, Summary, Info, CollectorRegistry
-from threading import Lock
-from loguru import logger; logger = logger.opt(colors=True)
-import time
-
-from datetime import datetime,timedelta
-import wandb
-import pandas
-
-# Torch
-import torch
-import torch.nn.functional as F
-from torch.nn.utils.rnn import pad_sequence
-from torch.nn.utils import clip_grad_norm_
-
-from rich import print
-from rich.console import Console
-from rich.style import Style
-import commune as c
-
-class neuron(c.Module):
- r"""
- Creates a bittensor neuron that specializes in the serving. The template server miner
- serves a NLP model from huggingface on the bittensor network. By default, the model does
- not train itself and thus requires less memory to run.
-
- Args:
- config (:obj:`bittensor.Config`, `optional`):
- bittensor.server.config()
- subtensor (:obj:bittensor.subtensor , `optional`):
- bittensor subtensor connection
- wallet (:obj:bittensor.wallet, `optional`):
- bittensor wallet object
- axon (:obj:bittensor.axon, `optional`):
- bittensor axon object
- metagraph (:obj:bittensor.metagraph, `optional`):
- bittensor metagraph object
- lasthidden (:obj:bool, `optional`):
- lasthidden synapse control
- causallm (:obj:bool, `optional`):
- causallm synapse control
- causallmnext (:obj:bool, `optional`):
- causallmnext synapse control
- seq2seq (:obj:bittensor.metagraph, `optional`):
- seq2seq synapse control
- synapse_list (:obj:list of int, `optional`):
-
-
- Examples::
- >>> subtensor = bittensor.subtensor(network='nakamoto')
- >>> server = bittensor.neuron.text.core_server.neuron(subtensor=subtensor)
- >>> server.run()
- """
- def __init__(
- self,
- config: 'bittensor.config' = None,
- subtensor: 'bittensor.subtensor' = None,
- wallet: 'bittensor.wallet' = None,
- axon: 'bittensor.axon' = None,
- metagraph: 'bittensor.metagraph' = None,
- model: 'bittensor.neurons.text.core_server.server' = None,
- lasthidden = None,
- causallm = None,
- causallmnext = None,
- seq2seq = None,
- synapse_list = None,
- netuid = None,
- blacklist_hotkeys = None,
- ):
- if config is None:
- config = server.config()
-
- config = config;
-
- config.netuid = netuid if netuid != None else config.netuid
-
- if synapse_list != None:
- config.neuron.lasthidden = False
- config.neuron.causallm = False
- config.neuron.causallmnext = False
- config.neuron.seq2seq = False
-
- if bittensor.proto.Synapse.SynapseType.TEXT_LAST_HIDDEN_STATE in synapse_list:
- config.neuron.lasthidden = True
-
- if bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM in synapse_list:
- config.neuron.causallm = True
-
- if bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM_NEXT in synapse_list:
- config.neuron.causallmnext = True
-
- if bittensor.proto.Synapse.SynapseType.TEXT_SEQ_2_SEQ in synapse_list:
- config.neuron.seq2seq = True
-
- config.neuron.lasthidden = lasthidden if lasthidden != None else config.neuron.lasthidden
- config.neuron.causallm = causallm if causallm != None else config.neuron.causallm
- config.neuron.causallmnext = causallmnext if causallmnext is not None else config.neuron.causallmnext
- config.neuron.seq2seq = seq2seq if seq2seq != None else config.neuron.seq2seq
- config.neuron.blacklist.hotkeys = blacklist_hotkeys if blacklist_hotkeys != None else config.neuron.blacklist.hotkeys
-
- self.check_config( config )
- self.config = config
-
- bittensor.logging (
- config = config,
- logging_dir = config.neuron.full_path,
- )
-
- # --- Setup prometheus summaries.
- # These will not be posted if the user passes --prometheus.level OFF
- registry = CollectorRegistry()
- self.prometheus_counters = Counter('neuron_counters', 'Counter sumamries for the running server-miner.', ['neuron_counters_name'], registry=registry)
- self.prometheus_guages = Gauge('neuron_guages', 'Guage sumamries for the running server-miner.', ['neuron_guages_name'], registry=registry)
- self.prometheus_info = Info('neuron_info', "Info sumamries for the running server-miner.", registry=registry)
- self.config.to_prometheus()
-
- if self.config.netuid == None and self.config.subtensor.network != 'nakamoto':
- subtensor = bittensor.subtensor(config = config) if subtensor == None else subtensor
- self.config.netuid = subtensor.get_subnets()[0]
-
- self.mutex = Lock()
-
- if isinstance(model, str) or isinstance(model, list):
- self.model = model
- else:
- self.model = server(config = config).to(config.neuron.device) if model == None else model
- self.subtensor = bittensor.subtensor(config = config) if subtensor == None else subtensor
- self.wallet = bittensor.wallet( config = config ) if wallet == None else wallet
- self.metagraph = bittensor.metagraph ( config = config, netuid = self.config.netuid) if metagraph == None else metagraph
- self.timecheck_dicts = {bittensor.proto.RequestType.FORWARD:{}, bittensor.proto.RequestType.BACKWARD:{}}
-
- self.config.neuron.max_batch_size = self.subtensor.validator_batch_size(netuid=self.config.netuid) if self.config.neuron.max_batch_size == -1 else self.config.neuron.max_batch_size
- self.config.neuron.max_sequence_len = self.subtensor.validator_sequence_length(netuid=self.config.netuid) if self.config.neuron.max_sequence_len == -1 else self.config.neuron.max_sequence_len
-
- if axon == None:
- axon = bittensor.axon(
- config = config,
- wallet = wallet,
- netuid = self.config.netuid,
- synapse_checks=self.synapse_check,
- synapse_last_hidden = self.forward_hidden_state if config.neuron.lasthidden else None,
- synapse_causal_lm = self.forward_casual_lm if config.neuron.causallm else None,
- synapse_causal_lm_next = self.forward_casual_lm_next if config.neuron.causallmnext else None,
- synapse_seq_2_seq = self.forward_generate if config.neuron.seq2seq else None ,
- blacklist = self.blacklist if not config.neuron.disable_blacklist else None,
- priority = self.priority if not config.neuron.disable_priority else None,
- )
- self.axon = axon
- self.query_data = {}
-
- # Init prometheus.
- # By default we pick the prometheus port to be axon.port - 1000 so that we can match port to server.
- bittensor.prometheus (
- config = config,
- wallet = self.wallet,
- netuid = self.config.netuid,
- port = config.prometheus.port if config.axon.port == bittensor.defaults.axon.port else config.axon.port - 1000
- )
-
- # Verify subnet exists
- if self.config.subtensor.network != 'nakamoto' and not self.subtensor.subnet_exists( netuid = self.config.netuid ):
- bittensor.__console__.print(f"[red]Subnet {self.config.netuid} does not exist[/red]")
- sys.exit(1)
-
- @classmethod
- def config(cls):
- return server.config()
-
- @staticmethod
- def check_config( config: 'bittensor.Config' ):
- r""" Checks/validates the config namespace object.
- """
- bittensor.logging.check_config( config )
- bittensor.wallet.check_config( config )
- bittensor.subtensor.check_config( config )
- if hasattr(bittensor, 'metagraph') and hasattr(config, 'metagraph'):
- bittensor.metagraph.check_config( config )
- bittensor.dataset.check_config( config )
- bittensor.axon.check_config( config )
- if hasattr(bittensor, 'wandb') and hasattr(config, 'wandb'):
- bittensor.wandb.check_config( config )
- bittensor.prometheus.check_config( config )
- full_path = os.path.expanduser('{}/{}/{}/netuid{}/{}'.format( config.logging.logging_dir, config.wallet.get('name', bittensor.defaults.wallet.name), config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey), config.netuid, config.neuron.name ))
- config.neuron.full_path = os.path.expanduser(full_path)
- if not os.path.exists(config.neuron.full_path):
- os.makedirs(config.neuron.full_path)
-
- def run(
- self,
- ):
- self.config.to_defaults()
-
- # Load/Create our bittensor wallet.
- self.wallet.reregister(subtensor=self.subtensor, netuid = self.config.netuid)
- self.metagraph.sync(netuid = self.config.netuid, subtensor=self.subtensor).save()
-
- # Create our optimizer.
-
- # optimizer = torch.optim.SGD(
- # [ {"params": self.model.parameters()} ],
- # lr = self.config.neuron.learning_rate,
- # momentum = self.config.neuron.momentum,
- # )
-
- # self.prometheus_guages.labels( 'model_size_params' ).set( sum(p.numel() for p in self.model.parameters()) )
- # self.prometheus_guages.labels( 'model_size_bytes' ).set( sum(p.element_size() * p.nelement() for p in self.model.parameters()) )
- self.prometheus_info.info ({
- 'type': "core_server",
- 'uid': str(self.metagraph.hotkeys.index( self.wallet.hotkey.ss58_address )),
- 'netuid': self.config.netuid,
- 'network': self.config.subtensor.network,
- 'coldkey': str(self.wallet.coldkeypub.ss58_address),
- 'hotkey': str(self.wallet.hotkey.ss58_address),
- })
-
- # Create our axon server and subscribe it to the network.
- self.axon.start().serve(subtensor=self.subtensor)
- self.axon.attach_backward_callback(self.backward_callback)
-
-
- # Training Data
- if self.config.neuron.local_train:
- self.dataset = bittensor.dataset(config=self.config)
- self.dataset.set_data_size(10, 64)
- data = next(self.dataset)
-
- # # load our old model
- # if not self.config.neuron.restart :
- # self.model.load(self.config.neuron.full_path)
-
-
- if hasattr(self.config, 'wandb') and self.config.wandb.api_key != 'default':
- # --- Init Wandb.
- bittensor.wandb(
- config = self.config,
- cold_pubkey = self.wallet.coldkeypub.ss58_address,
- hot_pubkey = self.wallet.hotkey.ss58_address,
- root_dir = self.config.neuron.full_path
- )
-
- last_set_block = self.subtensor.get_current_block()
- blocks_per_set_weights = self.get_blocks_per_set_weights()
- epoch_starting_successes = self.axon.stats.total_successes
- epoch_starting_requests = self.axon.stats.total_requests
- # --- Run Forever.
- while True:
- iteration = 0
- local_data = {}
- self.query_data = {}
- nn = self.get_neuron()
- uid = self.metagraph.hotkeys.index( self.wallet.hotkey.ss58_address )
- current_block = self.subtensor.get_current_block()
- end_block = current_block + self.config.neuron.blocks_per_epoch
-
- if self.config.neuron.local_train and False:
- # --- Training step.
- while end_block >= current_block:
- if current_block != self.subtensor.get_current_block() and self.axon.priority_threadpool.is_empty:
- with self.mutex:
- logger.info(f'local training\titeration: {iteration}\tstart')
- loss, _ = self.model( next(self.dataset).to(self.model.device) )
- if iteration > 0 :
- losses += loss
- else:
- losses = loss
- iteration += 1
- current_block = self.subtensor.get_current_block()
- logger.info(f'local training\titeration: {iteration}\tloss: {loss}')
- else:
- time.sleep(1)
-
- if iteration != 0:
- (losses/iteration).backward()
-
- else:
- while end_block > current_block:
- time.sleep(12)
- current_block = self.subtensor.get_current_block()
-
- # --- Update parameters
- if (self.config.neuron.local_train and iteration > 0) or (self.config.neuron.remote_train and self.model.backward_gradients_count > 0):
- # Custom learning rate
- if self.model.backward_gradients_count > 0:
- optimizer.param_groups[0]['lr'] = 0.1/(self.model.backward_gradients_count)
- else:
- optimizer.param_groups[0]['lr'] = 0.1
-
- logger.info('Optmization Started')
- with self.mutex:
- clip_grad_norm_(self.model.parameters(), 1.0)
- optimizer.step()
- optimizer.zero_grad()
- logger.info('Optimization Successful: Model updated')
-
- if (self.config.neuron.local_train and iteration > 0):
- local_data = {'local/loss': losses.detach().item() / iteration}
-
- if local_data['local/loss'] < self.model.best_loss:
- self.model.best_loss = local_data['local/loss']
- self.model.save(self.config.neuron.full_path)
-
- # Save it only when it gives a low average loss over a large sample size (config.neuron.num_remote_loss), default to 20.
- elif (self.config.neuron.remote_train and len(self.model.remote_losses) >= self.config.neuron.num_remote_loss):
- local_data = {'local/remote_loss': sum(self.model.remote_losses) / len(self.model.remote_losses)}
-
- if local_data['local/remote_loss'] < self.model.best_remote_loss:
- self.model.best_remote_loss = local_data['local/remote_loss']
- self.model.save(self.config.neuron.full_path)
-
- self.model.remote_losses = []
-
- self.model.backward_gradients_count = 0
-
- data = {
- 'stake': nn.stake,
- 'rank': nn.rank,
- 'trust': nn.trust,
- 'consensus': nn.consensus,
- 'incentive': nn.incentive,
- 'emission': nn.emission,
- }
-
- if hasattr(self.config, 'wandb') and self.config.wandb.api_key != 'default':
-
- df = pandas.concat( [
- bittensor.utils.indexed_values_to_dataframe( prefix = 'w_i_{}'.format(nn.uid), index = self.metagraph.uids, values = self.metagraph.W[:, uid] ),
- self.axonaxon.to_dataframe( metagraph = self.metagraph ),
- ], axis = 1)
- df['uid'] = df.index
- wandb_info_axon = self.axon.to_wandb()
- wandb.log( { **data, **wandb_info_axon, **local_data }, step = current_block )
- wandb.log( { 'stats': wandb.Table( dataframe = df ) }, step = current_block )
-
- # === Prometheus logging.
- self.prometheus_guages.labels("stake").set( nn.stake )
- self.prometheus_guages.labels("rank").set( nn.rank )
- self.prometheus_guages.labels("trust").set( nn.trust )
- self.prometheus_guages.labels("consensus").set( nn.consensus )
- self.prometheus_guages.labels("validator_trust").set( nn.validator_trust )
- self.prometheus_guages.labels("incentive").set( nn.incentive )
- self.prometheus_guages.labels("emission").set( nn.emission )
-
- print(f"[white not bold]{datetime.now():%Y-%m-%d %H:%M:%S}[/white not bold]{' ' * 4} | "
- f"{f'[magenta dim not bold]#{current_block}[/magenta dim not bold]'.center(16 + len('[magenta dim not bold][/magenta dim not bold]'))} | "
- f'[green not bold]{current_block - last_set_block}[/green not bold]/'
- f'[white not bold]{blocks_per_set_weights}[/white not bold] [dim]blocks/epoch[/dim] | '
- f'[bright_green not bold]{self.axon.stats.total_successes - epoch_starting_successes}[/bright_green not bold]'
- f'[white]/{self.axon.stats.total_requests - epoch_starting_requests}[/white] '
- f'[dim]Epoch Success [/dim]|'
- f'[dim][green] {self.axon.stats.total_successes}[/green]'
- f'[white]/{self.axon.stats.total_requests}[/white]'
- f' Total Success [/dim]|'
- f'[dim white not bold][yellow] {self.axon.stats.total_codes[bittensor.proto.ReturnCode.Name(2)]}[/yellow]'
- f'[white]/{self.axon.stats.total_requests}[/white]'
- f' Timeout [/dim white not bold]|'
- f'[dim white not bold][red] {self.axon.stats.total_requests - self.axon.stats.total_successes - self.axon.stats.total_codes[bittensor.proto.ReturnCode.Name(2)]}[/red]'
- f'[white]/{self.axon.stats.total_requests}[/white]'
- f' Error [/dim white not bold]|')
-
-
- if current_block - last_set_block > blocks_per_set_weights:
- self.metagraph.sync(netuid=self.config.netuid, subtensor = self.subtensor)
- last_set_block = current_block
- epoch_starting_successes = self.axon.stats.total_successes
- epoch_starting_requests = self.axon.stats.total_requests
-
- print(f"[white not bold]{datetime.now():%Y-%m-%d %H:%M:%S}[/white not bold]{' ' * 4} | "
- f"{f'UID [bright_cyan]{uid}[/bright_cyan]'.center(16 + len('[bright_cyan][/bright_cyan]'))} | "
- f'[dim white not bold] [green]{str(nn.stake):.4}[/green] Stake [/dim white not bold]'
- f'[dim white not bold]| [yellow]{nn.trust:.3}[/yellow] Trust [/dim white not bold]'
- f'[dim white not bold]| [green]{nn.incentive:.3}[/green] Incentive [/dim white not bold]')
-
- if not self.config.neuron.no_set_weights:
- try:
- # Set self weights to maintain activity.
- # --- query the chain for the most current number of peers on the network
- chain_weights = torch.zeros(self.get_neuron_num())
- chain_weights [ uid ] = 1
- did_set = self.subtensor.set_weights(
- uids=torch.arange(0,len(chain_weights)),
- netuid = self.config.netuid,
- weights = chain_weights,
- wait_for_inclusion = False,
- wallet = self.wallet,
- )
- if did_set:
- logger.success('Successfully set weights on the chain')
- else:
- logger.error('Failed to set weights on chain. (Timeout)')
-
- except Exception as e:
- logger.error('Failure setting weights on chain with error: {}', e)
-
- def synapse_check(self, synapse, hotkey, inputs_x=None):
- """
- Custom synapse function to protect certain synapse functions depending on the stake and weight.
- Certain synapses require more compute than others. For instance, TEXT_SEQ_2_SEQ requires a significantly
- more commitment by the server than a requeset for TEXT_CAUSAL_LM_NEXT.
-
- Args:
- synapse (:obj:`bittensor.proto.SynapseArgs`, `required`):
- The proto message that contains additional args for individual synapse functions
- hotkey (:obj:`torch.FloatTensor`, `required`):
- The hotkey that sent the request
-
- """
- ## Uid that sent the request
- try:
- incoming_uid = self.metagraph.hotkeys.index(hotkey)
- except Exception as e:
- if self.config.neuron.blacklist_allow_non_registered:
- return False
- return True
-
- batch_size, sequence_len = inputs_x[0].size()
- if synapse.synapse_type == bittensor.proto.Synapse.SynapseType.TEXT_LAST_HIDDEN_STATE:
- if self.metagraph.S[incoming_uid] < self.config.neuron.lasthidden_stake \
- or (batch_size > self.config.neuron.max_batch_size) \
- or (sequence_len > self.config.neuron.max_sequence_len):
- return False
-
- elif synapse.synapse_type == bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM:
- if (self.metagraph.S[incoming_uid] < self.config.neuron.causallm_stake) \
- or (batch_size > self.config.neuron.max_batch_size) \
- or (sequence_len > self.config.neuron.max_sequence_len):
- return False
-
- elif synapse.synapse_type == bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM_NEXT:
- if (self.metagraph.S[incoming_uid] < self.config.neuron.causallmnext_stake) \
- or (batch_size > self.config.neuron.max_batch_size) \
- or (sequence_len > self.config.neuron.max_sequence_len):
- return False
-
- elif synapse.synapse_type == bittensor.proto.Synapse.SynapseType.TEXT_SEQ_2_SEQ:
- if (self.metagraph.S[incoming_uid] < self.config.neuron.seq2seq_stake) \
- or (batch_size > self.config.neuron.max_batch_size) \
- or (sequence_len > self.config.neuron.max_sequence_len) \
- or (self.metagraph.W[incoming_uid, self.uid]):
- return False
- else:
- raise Exception('Unknown Synapse')
-
- return True
-
- def backward_callback(self, inputs_x:torch.FloatTensor, grads_dy:torch.FloatTensor, synapses=[] ):
- """
- The default backward callback when no callback is attached: Is used to call specific synapse functions
-
- Args:
- inputs_x (:obj:`torch.FloatTensor`, `required`):
- The inputs that will be passed to the synapse functions
- grads_dy (:obj:`torch.FloatTensor`, `required`):
- The gradients that will be passed to the synapse functions
- synapses (:obj: list of bittensor.proto.SynapseArgs, 'Optional')
- The proto message that contains additional args for individual synapse functions
-
- Returns:
- response_tensors: (:obj: list of bittensor.proto.Tensor, `required`):
- serialized tensor response from the nucleus call or None.
- response_codes: (:obj: list of bittensor.proto.ReturnCode, `required`)
- return code associated with forward call i.e. Success of Timeout.
- response_messages: (:obj: list of strings, `required`)
- return message associated with synapse call
- """
- # --- initialize response variables ---
- response_tensors = []
- response_codes = []
- response_messages = []
-
- if not self.config.neuron.remote_train:
- return response_tensors, response_codes, response_messages
-
- # --- calling attached synapses ---
- with self.mutex and torch.enable_grad() and torch.autograd.set_detect_anomaly(True):
- for index, synapse in enumerate(synapses):
- try:
- if synapse.synapse_type in self.axon.synapse_callbacks and self.axon.synapse_callbacks[synapse.synapse_type] != None:
- message, model_output, response_tensor = self.axon.synapse_callbacks[synapse.synapse_type](inputs_x[index], synapse)
- grads_dy_norm = grads_dy[index]/(grads_dy[index].sum() + 0.00001)
- torch.autograd.backward (
- tensors = [ response_tensor ],
- grad_tensors = [ grads_dy_norm ],
- retain_graph=True
- )
- # Only consider loss from causal LM next.
- if synapse.synapse_type == bittensor.proto.Synapse.SynapseType.TEXT_CAUSAL_LM_NEXT:
- self.model.remote_losses.append(model_output.loss)
- self.model.remote_losses = self.model.remote_losses[-self.config.neuron.num_remote_loss:] if len(self.model.remote_losses) > self.config.neuron.num_remote_loss else self.model.remote_losses
- self.model.backward_gradients_count += inputs_x[index].size(0)
- response_tensors.append(None)
- response_codes.append(bittensor.proto.ReturnCode.Success)
- response_messages.append('Success')
-
- else:
- response_tensors.append(None)
- response_codes.append(bittensor.proto.ReturnCode.NotImplemented)
- response_messages.append('Not Implemented')
- except Exception as e:
- # --- Exception Hit in Synapse ---
- response_tensors.append(None)
- response_codes.append(bittensor.proto.ReturnCode.UnknownException)
- response_messages.append(str(e))
-
- return response_tensors, response_codes, response_messages
-
-
- def priority(self, pubkey:str, request_type:bittensor.proto.RequestType, inputs_x) -> float:
- r"""Calculates the priority on requests based on stake and size of input
- Args:
- pubkey ( str, `required`):
- The public key of the caller.
- inputs_x ( :obj:`torch.Tensor`, `required`):
- torch inputs to be forward processed.
- request_type ( bittensor.proto.RequestType, `required`):
- the request type ('FORWARD' or 'BACKWARD').
- """
- try:
- uid = self.metagraph.hotkeys.index(pubkey)
- priority = self.metagraph.S[uid].item()
-
- except:
- # zero priority for those who are not registered.
- priority = 0
-
- return priority
-
- def forward_generate(self, inputs_x:torch.FloatTensor, synapse, model_output = None):
- tokens = self.model.token_remap(inputs_x.to(self.model.device))
- output = self.model.pre_model.generate(
- input_ids=tokens['input_ids'],
- attention_mask=tokens['attention_mask'],
- max_length=max(tokens['input_ids'].shape[1] + 1, synapse.num_to_generate),
- num_beams=synapse.num_beams,
- no_repeat_ngram_size=synapse.no_repeat_ngram_size,
- early_stopping = synapse.early_stopping,
- do_sample=synapse.do_sample,
- top_p=synapse.top_p,
- num_return_sequences=synapse.num_return_sequences,
- temperature = synapse.temperature,
- repetition_penalty = synapse.repetition_penalty,
- length_penalty = synapse.length_penalty,
- max_time = synapse.max_time,
- num_beam_groups = synapse.num_beam_groups,
- )
- raw_texts = [self.model.tokenizer.decode(out) for out in output]
- tokens = [self.model.std_tokenizer.encode(raw_text, return_tensors="pt")[:,:synapse.num_to_generate].view(-1) for raw_text in raw_texts]
- bittensor_output = pad_sequence(tokens, batch_first=True)
- return None, model_output, bittensor_output
-
- def forward_hidden_state(self, inputs_x:torch.FloatTensor, synapse, model_output = None):
- with self.mutex:
- message, model_output, hidden = self.model.encode_forward(inputs_x.to(self.model.device), model_output=model_output)
- return message, model_output, hidden
-
- def forward_casual_lm(self, inputs_x:torch.FloatTensor, synapse, model_output = None):
- with self.mutex:
- message, model_output, logits = self.model.encode_forward_causallm(inputs_x.to(self.model.device), model_output=model_output)
- return message, model_output, logits
-
-
- def resolve_model(self, model):
-
- self.new_event_loop()
-
-
- return model
-
- def forward_casual_lm_next(self,inputs_x: torch.FloatTensor, synapse, model_output=None, max_trials=3, n=1, timeout=4):
-
- with self.mutex:
-
- if isinstance(self.model, str):
- self.new_event_loop()
- model = self.connect(self.model)
- else:
- model = self.model
-
-
- for i in range(max_trials):
-
- try:
- response = model.encode_forward_causallmnext(inputs_x,topk=synapse.topk,model_output=model_output)
- message, model_output, topk_token_phrases = response
- return message, model_output, topk_token_phrases
- except Exception as e:
- print(f'Failed, trying again trial: {i}/{max_trials} from error {e}')
-
- # topk_token_phrases: [sum_b(sum_k(len(phrase_k) + 1)_b)] contains topk token phrases and probabilities
- # Compacted 1-D tensor >= batch_size * (2 * topk + 1)
- return message, model_output, topk_token_phrases
-
-
- def blacklist(self, pubkey:str, request_type:bittensor.proto.RequestType) -> bool:
- r"""Axon security blacklisting, used to blacklist message from low stake members
- Args:
- pubkey ( str, `required`):
- The public key of the caller.
- request_type ( bittensor.proto.RequestType, `required`):
- the request type ('FORWARD' or 'BACKWARD').
- """
- # Check for registrations
- def registration_check():
- # If we allow non-registered requests return False = not blacklisted.
- is_registered = pubkey in self.metagraph.hotkeys
- if not is_registered:
- if self.config.neuron.blacklist_allow_non_registered:
- return False
-
- self.prometheus_counters.labels("blacklisted.registration").inc()
-
- raise Exception('Registration blacklist')
-
- # Check for stake
- def stake_check() -> bool:
- # Check stake.
- uid = self.metagraph.hotkeys.index(pubkey)
- if self.metagraph.S[uid].item() < self.config.neuron.blacklist.stake:
- self.prometheus_counters.labels("blacklisted.stake").inc()
-
- raise Exception('Stake blacklist')
- return False
-
- # Check for time
- def time_check():
- current_time = datetime.now()
- # Only check if the request are forward requests
- timecheck = self.timecheck_dicts[request_type]
- if pubkey in timecheck.keys():
- prev_time = timecheck[pubkey]
- if current_time - prev_time >= timedelta(seconds=self.config.neuron.blacklist.time):
- timecheck[pubkey] = current_time
- else:
- timecheck[pubkey] = current_time
- self.prometheus_counters.labels("blacklisted.time").inc()
-
- raise Exception('Time blacklist')
- else:
- timecheck[pubkey] = current_time
-
- return False
-
- # Check for hotkeys
- def hotkey_check():
- # Only check if the request are forward requests
- if (pubkey in self.config.neuron.blacklist.hotkeys):
- raise Exception('Hotkey blacklist')
- return False
-
- # Black list or not
- try:
- registration_check()
- time_check()
- stake_check()
- hotkey_check()
- return False, None
- except Exception as error:
- self.prometheus_counters.labels("blacklisted").inc()
- return True, error
-
- def get_neuron(self):
- if self.subtensor.network == 'nakamoto':
- nn = self.subtensor.neuron_for_pubkey(self.wallet.hotkey.ss58_address)
- else:
- nn = self.subtensor.get_neuron_for_pubkey_and_subnet(self.wallet.hotkey.ss58_address, netuid = self.config.netuid)
- return nn
-
- def get_neuron_num(self):
- if self.subtensor.network == 'nakamoto':
- n = self.subtensor.n()
- else:
- n = self.subtensor.subnetwork_n( netuid = self.config.netuid)
- return n
-
- def get_blocks_per_set_weights(self):
- blocks_per_set_weights = self.config.neuron.blocks_per_set_weights
- if blocks_per_set_weights == -1:
- if self.subtensor.network == 'nakamoto':
- blocks_per_set_weights = self.subtensor.validator_epoch_length
- else:
- blocks_per_set_weights = self.subtensor.validator_epoch_length(self.config.netuid)
-
- return blocks_per_set_weights
\ No newline at end of file
diff --git a/commune/modules/bittensor/miner/server.py b/commune/modules/bittensor/miner/server.py
deleted file mode 100644
index 9823a38a5..000000000
--- a/commune/modules/bittensor/miner/server.py
+++ /dev/null
@@ -1,707 +0,0 @@
-import argparse
-import math
-import bittensor
-import torch
-from torch import nn
-import torch.nn.functional as F
-from types import SimpleNamespace
-from typing import Tuple, Optional
-import os
-import transformers
-from transformers import AutoModel,AutoTokenizer,AutoConfig, AutoModelForCausalLM
-from torch.nn.utils.rnn import pad_sequence
-from bittensor.utils.tokenizer_utils import prep_tokenizer, get_translation_map, translate_logits_to_probs_std, \
- translate_special_token_text, pad_offsets, topk_token_phrases, compact_topk_token_phrases
-
-from loguru import logger; logger = logger.opt(colors=True)
-import commune as c
-
-
-
-shortcuts = {
- # 0-1B models
- 'gpt125m': 'EleutherAI/gpt-neo-125m',
-
- # 1-3B models
- 'gpt2.7b': 'EleutherAI/gpt-neo-2.7B',
- 'gpt3b': 'EleutherAI/gpt-neo-2.7B',
- 'opt1.3b': 'facebook/opt-1.3b',
- 'opt2.7b': 'facebook/opt-2.7b',
- # 'gpt3btuning' : ''
-
- # 0-7B models
- 'gptjt': 'togethercomputer/GPT-JT-6B-v1',
- 'gptjt_mod': 'togethercomputer/GPT-JT-Moderation-6B',
- 'gptj': 'EleutherAI/gpt-j-6b',
- 'gptj.pyg6b': 'PygmalionAI/pygmalion-6b',
- 'gpt6b': 'cerebras/Cerebras-GPT-6.7B',
- 'gptj.instruct': 'nlpcloud/instruct-gpt-j-fp16',
- 'gptj.codegen': 'moyix/codegen-2B-mono-gptj',
- 'gptj.hivemind': 'hivemind/gpt-j-6B-8bit',
- 'gptj.adventure': 'KoboldAI/GPT-J-6B-Adventure',
- 'gptj.pygppo': 'TehVenom/GPT-J-Pyg_PPO-6B',
- 'gptj.alpaca.gpt4': 'vicgalle/gpt-j-6B-alpaca-gpt4',
- 'gptj.alpaca': 'bertin-project/bertin-gpt-j-6B-alpaca',
- 'oa.galactia.6.7b': 'OpenAssistant/galactica-6.7b-finetuned',
- 'opt6.7b': 'facebook/opt-6.7b',
- 'llama': 'decapoda-research/llama-7b-hf',
- 'vicuna.13b': 'lmsys/vicuna-13b-delta-v0',
- 'vicuna.7b': 'lmsys/vicuna-7b-delta-v0',
- 'llama-trl': 'trl-lib/llama-7b-se-rl-peft',
- 'opt.nerybus': 'KoboldAI/OPT-6.7B-Nerybus-Mix',
- 'pygmalion-6b': 'PygmalionAI/pygmalion-6b',
- # # > 7B models
- 'oa.pythia.12b': 'OpenAssistant/oasst-sft-1-pythia-12b',
- 'gptneox': 'EleutherAI/gpt-neox-20b',
- 'gpt20b': 'EleutherAI/gpt-neox-20b',
- 'opt13b': 'facebook/opt-13b',
- 'gpt13b': 'cerebras/Cerebras-GPT-13B',
- 'gptjvr': os.path.expanduser('~/models/gpt-j-6B-vR'),
- 'stablellm7b': 'StabilityAI/stablelm-tuned-alpha-7b',
- 'fish': os.path.expanduser('~/fish_model'),
-
- }
-
-
-
-
-class server(c.Module,torch.nn.Module):
- shortcuts = shortcuts
- def __init__(self,
- config: 'bittensor.config' = None,
- pretrained: bool = None,
- model_name: str = None,
- padding: bool =None,
- interpolate: bool =None,
- inter_degree: str = None,
- model = None,
- tokenizer = None,
- mapping_function = None,
- token_remap = None,
- device = None,
- checking= None):
- r"""" Creates a server that serves up a pretrained miner on the bittensor network
- Args:
- config (:obj:`bittensor.Config`, `required`):
- bittensor.server.config()
- pretrained (:obj:bool , `optional`):
- if the model should pretrained or not
- model_name (:obj:string , `optional`):
- name of the pretrained model from huggingface to use
- padding (:obj:bool, `optional`):
- If the server should pad out to match the hidden units that the bittensor network is using
- If set to False, it will instead create a mapping layer to do the same thing.
- interpolate (:obj:bool, `optional`):
- If the server should interpolate between sequence length differences.
- If set to false, there should be a mapping function that takes care of the differnces
- inter_degree (:obj:str, `optional`):
- The Interpolate algorithm (nearest | linear | bilinear | bicubic | trilinear | area)
- model (:obj:torch.module, `optional`):
- Overrides the huggingface pretrained model with your own pretrained model
- tokenizer (:obj:huggingface.tokenizer, `optional`):
- Overrides the huggingface tokenizer with your tokenizer
- mapping_function (:obj:Callable, `optional`):
- Custom mapping function that maps between sequence length differences between tokenizers
- token_remap (:obj:Callable, `optional`):
- Custom function that maps between tokenizers (defaults to self.remapping_token)
- """
- torch.nn.Module.__init__(self)
- if config == None: config = server.config()
-
- if isinstance(config, dict):
- config = c.munch(config)
- self.config = config;c.print(config)
- self.std_tokenizer = bittensor.tokenizer()
-
-
-
- #setting up pretrained model
- model_name = model_name if model_name != None else config.neuron.model_name
- self.model_name = self.shortcuts.get(model_name , model_name )
-
- self.pretrained = pretrained if pretrained != None else config.neuron.pretrained
- if self.pretrained == True:
- self.pre_model = model if model != None else AutoModelForCausalLM.from_pretrained(self.model_name)
- self.tokenizer = tokenizer
- if tokenizer is None:
- try:
- self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
- except ValueError: # when fast not available as in https://github.com/huggingface/tokenizers/pull/1005
- self.tokenizer = AutoTokenizer.from_pretrained(self.model_name, use_fast=False)
-
- elif self.pretrained == False:
- model_config = AutoConfig.from_pretrained(self.model_name)
- model_config.vocab_size= bittensor.__vocab_size__
- self.pre_model = model if model != None else AutoModel.from_config(model_config)
- self.tokenizer = bittensor.tokenizer()
-
- # Define PAD Token = EOS Token (GPT2 generate convention, when PAD Token is None)
- # https://github.com/huggingface/transformers/blob/49c8c67fb815a277405f84dea4a66353e19fb347/tests/models/gpt2/test_modeling_gpt2.py#L532
- if self.pre_model.config.pad_token_id is None and self.pre_model.config.eos_token_id is not None:
- self.pre_model.config.pad_token_id = self.pre_model.config.eos_token_id
-
- self.tokenizer = prep_tokenizer(self.tokenizer, self.std_tokenizer)
- self.to_translation_map = get_translation_map(self.tokenizer, self.std_tokenizer)
- self.from_translation_map = get_translation_map(self.std_tokenizer, self.tokenizer)
- self.split_map_cache = {}
-
- if self.config.neuron.local_train or self.config.neuron.remote_train:
- self.pre_model.train()
- self.set_fine_tuning_params()
-
- else:
- self.pre_model.eval()
-
-
- device = device if device != None else config.neuron.device
-
- if 'cuda' in device:
- gpu = int(device.split(':')[1]) if device.split(':')[1] != '' else 0
- free_gpu_memory = self.free_gpu_memory()
- model_size = self.get_model_size(self.model_name )
- if free_gpu_memory[gpu] < model_size:
- gpu = self.most_free_gpu()
- assert free_gpu_memory[gpu] > model_size, "Not enough free memory on any GPU to load model. Try reducing the batch size."
- device = f'cuda:{gpu}'
- else:
- device = 'cpu'
-
- self.device = device
-
-
-
-
- if self.config.neuron.autocast and self.device[:4] == 'cuda':
- self.pre_model.half()
-
-
- self.pre_model.to(self.device)
- #parameters of the models
- self.final_dim = bittensor.__network_dim__
- self.pre_dimension = self.pre_model.config.hidden_size
- self.padding = padding if padding != None else config.neuron.padding
- self.interpolate = interpolate if interpolate != None else config.neuron.interpolate
- self.inter_degree = inter_degree if inter_degree != None else config.neuron.inter_degree
- self.checking = checking if checking != None else config.neuron.checking
- self.mapping_function= mapping_function
- self.token_remap = token_remap if token_remap is not None else self.remapping_token
-
-
- if self.config.neuron.padding == False:
- self.mapping = torch.nn.Linear( self.pre_dimension, self.final_dim)
-
- self.decoder = torch.nn.Linear( self.final_dim, bittensor.__vocab_size__ , bias=False)
- self.loss_fct = torch.nn.CrossEntropyLoss()
-
- self.outputs_cache = None
- self.gradients_cache = None
- self.best_loss = math.inf
- self.best_remote_loss = math.inf
-
- #checking if the parameters of the server makes sense
- if self.checking and pretrained == True:
- self.check()
-
- # -- keeps track of gradients applied
- self.backward_gradients_count = 0
- self.remote_losses = []
-
-
-
- def set_fine_tuning_params(self) -> Tuple[bool, str]:
- r''' Set to tune only the parameter of the last layer
- Returns:
- reached_last_layer (:type:`bool`):
- If we have set partial of the model to requires grad.
-
- last_layer_name (:type:`string`):
- The name of the last layer that user specified or we found.
- None if the user did not specify and we couldnt find it.
- '''
- def find_last_layer(model: torch.nn.Module) -> Optional[str]:
- r''' Recursively find the last layer in a nn.ModuleList
- Args:
- model (:obj:`torch.module`):
- The model (or sub-model) to fine the last layer from.
- Returns:
- name (:type:`str`):
- The name (or sub-name) of the last layer.
- None if not found
- '''
- reverted_child_list = [(name, child) for name, child in model.named_children()]
- reverted_child_list.reverse()
-
- for name, child in reverted_child_list:
- if isinstance(child, nn.ModuleList):
- if self.config.neuron.finetune.num_layers > len(child):
- logger.warning(f'Number of finetune layers was set higher then the layers avaliable {len(child)}')
- return None
- return (name + '.' +str(len(child) - self.config.neuron.finetune.num_layers))
-
- for name, child in reverted_child_list:
- name_ = find_last_layer(child)
- if name_ != None:
- return (name+'.'+ name_)
-
- return None
-
- if self.config.neuron.finetune.layer_name == None:
- last_layer_name = find_last_layer(self.pre_model)
- else:
- last_layer_name = self.config.neuron.finetune.layer_name
-
- reached_last_layer = False
-
- # set the non-last layer parameters not to require grads
- if (self.config.neuron.finetune.all) or (last_layer_name == None):
- return False, last_layer_name
-
- logger.success(f'Set to finetune layer {last_layer_name} and onwards')
-
- for name, param in self.pre_model.named_parameters():
- if last_layer_name in name or reached_last_layer == True:
- param.requires_grad = True
- reached_last_layer = True
- else:
- param.requires_grad = False
-
- if reached_last_layer == False:
- if self.config.neuron.finetune.all:
- logger.warning('Set to finetune the whole model, this will significantly increase the memory usage.')
- else:
- logger.warning(f'Cannot identify the last layer of the model with name {last_layer_name}, setting to finetune on all of the parameters.')
-
- return reached_last_layer, last_layer_name
-
- def remapping_token(self, token_batch, std_tokenizer=None, return_offsets_mapping=False):
- r""" Tokenizer remapping; decodes the message and then remaps the message using a new tokenizer
- Args:
- token_batch ( :obj:`torch.LongTensor`, `required`):
- token_batch to be retokenized, [batch_size, sequence_len]
- std_tokenizer ( :obj:`transformers.Tokenizer`, `optional`):
- The standard tokenizer which was used to tokenize the input.
- return_offsets_mapping ( :obj:`bool`, `required`):
- Return offsets_mapping in tokenization to delineate token segment positions.
- """
- if std_tokenizer is None:
- std_tokenizer = self.std_tokenizer
-
- text_batch = std_tokenizer.batch_decode(token_batch) # decode tokens to original text
- result = translate_special_token_text(text_batch, std_tokenizer, self.tokenizer) # translate special tokens
- to_text_batch, from_offsets_batch, to_offsets_batch, pad_offsets_batch = result
-
- tokens = self.tokenizer(to_text_batch, padding=True, truncation=True, max_length=token_batch.size(1), return_tensors='pt',
- add_special_tokens=False).to(self.device) # assume tokenizer.padding_side = 'left'
-
- if return_offsets_mapping: # get offsets_mapping in tokenization to delineate token segment positions
- server_tokens = self.tokenizer(to_text_batch, return_offsets_mapping=True, add_special_tokens=False)
- std_tokens = std_tokenizer(text_batch, return_offsets_mapping=True) # encode again to get offsets mapping
-
- # pad offsets so that special token offset widths match for continued correct alignment
- tokens['offset_mapping'] = pad_offsets(server_tokens['offset_mapping'], to_offsets_batch, pad_offsets_batch)
- tokens['offset_mapping_std'] = pad_offsets(std_tokens['offset_mapping'], from_offsets_batch,
- pad_offsets_batch)
- return tokens
-
- def forward(self, inputs, tokenizer=None):
- """
- Forward pass through the whole server model. Returns the loss and decoded predictions.
-
- Args:
- inputs ( :obj:`torch.Tensor`, `required`):
- torch inputs to be forward processed.
- tokenizer (:obj:'huggingface.tokenizer', optional):
- The tokenizer which was used to tokenize the inputs
- Returns:
- loss (:obj:`torch.FloatTensor`):
- MLM loss from the inputs
- decoded_targets (:obj:`torch.FloatTensor`):
- Decoded predictions of the next token in the sentence.
-
- """
- message, model_output, decoded_targets = self.local_forward(inputs, tokenizer)
- shift_logits = decoded_targets[..., :-1, :].contiguous()
- shift_labels = inputs[..., 1:].contiguous()
- loss = self.loss_fct( shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1) )
-
- return loss, decoded_targets
-
- def local_forward(self, token_batch, tokenizer=None, encode_len=bittensor.__network_dim__, model_output = None):
- r""" Forward pass through the pretrained model and possible mappings between hidden units.
- The response tensor should be the hidden units computed using the local context and
- with shape: [batch_size, sequence_len, __vocab_size__].
-
- Args:
- token_batch ( :obj:`torch.LongTensor`, `required`):
- torch inputs to be forward processed, [batch_size, sequence_len]
- tokenizer ( huggingface.tokenizer, `optional`):
- The tokenizer which was used to tokenize the inputs
- encode_len ( :obj:`int`, `optional`):
- logit encoding length, default bittensor.__network_dim__ length
- model_output (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `optional`):
- The output of huggingface auto model.
-
- Returns:
- model_outputs (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `required`):
- The output of huggingface auto model.
-
- logits (:obj:`torch.FloatTensor`):
- The nucleus's logit outputs as a torch tensor of shape [batch_size, sequence_len, __vocab_size__]
- """
- tokens = self.token_remap(token_batch, std_tokenizer=tokenizer, return_offsets_mapping=True) # remap to server tokenizer
- if model_output == None:
- if self.config.neuron.local_train:
- model_output = self.pre_model(input_ids=tokens['input_ids'],
- attention_mask=tokens['attention_mask'],
- output_hidden_states=True)
- else:
- with torch.no_grad():
- model_output = self.pre_model(input_ids=tokens['input_ids'],
- attention_mask=tokens['attention_mask'],
- output_hidden_states=True)
-
- self.model_output_check(model_output)
- return None, model_output, model_output.logits
-
- def encode_forward(self,inputs,tokenizer=None, model_output = None):
- r""" Forward pass through the pretrained model and possible mappings between hidden units.
- The response tensor should be the hidden units computed using the local context and with shape: [batch_size, sequence_len, __network_dim__].
-
- Args:
- inputs ( :obj:`torch.Tensor`, `required`):
- torch inputs to be forward processed.
- tokenizer ( huggingface.tokenizer, `optional`):
- The tokenizer which was used to tokenize the inputs
- model_outputs (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `optional`):
- The output of huggingface auto model.
-
- Returns:
- model_outputs (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `required`):
- The output of huggingface auto model.
-
- encoded_hidden (:type:`torch.Tensor`, `required`)
- The hidden layer output as a torch tensor of shape [batch_size, sequence_len, __network_dim__ ]
- """
- transformers.set_seed(0)
- transformers.enable_full_determinism(0)
-
- sen_len = inputs.size()
- tokens = self.token_remap(inputs, tokenizer) # remap to server tokenizer
-
- if model_output == None:
- if self.config.neuron.remote_train:
- model_output = self.pre_model(input_ids=tokens['input_ids'],
- attention_mask=tokens['attention_mask'],
- output_hidden_states=True)
- else:
- with torch.no_grad():
- model_output = self.pre_model(input_ids=tokens['input_ids'],
- attention_mask=tokens['attention_mask'],
- output_hidden_states=True)
-
- self.model_output_check(model_output)
- pre_hidden = model_output.hidden_states[-1]
-
- if self.interpolate and sen_len[1] != pre_hidden.size()[1]:
- down= F.interpolate(pre_hidden.unsqueeze(1),size=[sen_len[1],pre_hidden.size()[2]],mode=self.inter_degree).squeeze(1)
- elif self.mapping_function:
- down = self.mapping_function(pre_hidden)
- else:
- down = pre_hidden
-
- if self.padding:
- padding_l = (self.final_dim-self.pre_dimension)//2
- padding_r = (self.final_dim-self.pre_dimension) - padding_l
- encoded_hidden = F.pad(down, (padding_l, padding_r), "constant", 0)
- else:
- encoded_hidden = self.mapping(down)
-
- return None, model_output, encoded_hidden
-
- def encode_forward_causallm(self, token_batch, tokenizer=None, encode_len=bittensor.__network_dim__, model_output=None):
- r""" Forward pass through the pretrained model and possible mappings between hidden units.
- The response tensor should be the hidden units computed using the local context and
- with shape: [batch_size, sequence_len, __vocab_size__].
-
- Args:
- token_batch ( :obj:`torch.LongTensor`, `required`):
- torch inputs to be forward processed, [batch_size, sequence_len]
- tokenizer ( huggingface.tokenizer, `optional`):
- The tokenizer which was used to tokenize the inputs
- encode_len ( :obj:`int`, `optional`):
- logit encoding length, default bittensor.__network_dim__ length
- model_output (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `optional`):
- The output of huggingface auto model.
-
- Returns:
- model_outputs (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `required`):
- The output of huggingface auto model.
-
- logits_std (:obj:`torch.FloatTensor`):
- The nucleus's logit outputs as a torch tensor of shape [batch_size, sequence_len, __vocab_size__]
- """
- transformers.set_seed(0)
- transformers.enable_full_determinism(0)
-
- tokens = self.token_remap(token_batch, std_tokenizer=tokenizer, return_offsets_mapping=True) # remap to server tokenizer
-
- def _forward(_model_output=model_output):
- if _model_output is None:
- # transformer models like gerpt2 typically perform worse with left-side attention mask, so turning it off
- _model_output = self.pre_model(input_ids=tokens['input_ids'],
- #attention_mask=tokens['attention_mask'],
- output_hidden_states=True)
- self.model_output_check(_model_output)
- pre_logits = _model_output.logits # [batch_size, sequence_len, self.tokenizer.vocab_len]
- probs_std = translate_logits_to_probs_std(pre_logits,
- tokens['offset_mapping'], tokens['offset_mapping_std'],
- self.tokenizer, self.std_tokenizer,
- self.split_map_cache,
- self.to_translation_map, self.from_translation_map,
- tokens['input_ids'], token_batch)
- probs_std = probs_std.to(self.device)
- logits_std = torch.log(probs_std + 1e-40)
- #removing the loss calculation for stablity testing
- original_loss = self.get_loss_fct(pre_logits, tokens['input_ids']).item()
- translated_loss = self.get_loss_fct(logits_std, token_batch).item()
- message = f'Loss: {original_loss:.2f} → {translated_loss:.2f}'
-
- return message, _model_output, logits_std
-
- if self.config.neuron.remote_train:
- return _forward() # track gradients for training
-
- with torch.no_grad():
- return _forward() # no gradients
-
- def encode_forward_causallmnext(self, token_batch, std_tokenizer=None, topk: int = 4096, model_output=None):
- r"""
- Forward pass through the pretrained model and select topk tokenizer logits and retokenize with std_tokenizer,
- then compact new token phrases and probabilities
- into 1-D tensor [ >= batch_size * (2 * topk + 1)] prob + at least 1 token per phrase + floor_prob.
- The floor probability is the mean probability of token phrases not captured in topk, required since
- the server tokenizer vocab_size may not be known to the receiver/validator.
-
- Args:
- token_batch ( :obj:`torch.LongTensor`, `required`):
- torch inputs to be forward processed, [batch_size, std_sequence_len].
- std_tokenizer ( :obj:`PreTrainedTokenizerBase`, `optional`):
- The standard tokenizer which was used to tokenize the inputs.
- topk ( :obj:`int`, `optional`):
- Amount of std_tokenized server phrases with highest probability to produce.
- model_output (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `optional`):
- The output of transformers AutoModel.
-
- Returns:
- model_outputs (:obj:`transformers.modeling_outputs.BaseModelOutputWithCrossAttentions`, `required`):
- The output of transformers AutoModel.
- topk_tensor (:obj:`torch.Tensor`, `required`):
- [batch_size, (topk + 1), max_len] tensor includes topk token probabilities (prob_k) + floor_prob
- in first column with gradients attached, with std_tokens in remaining columns with ignore_index padding.
- Content structure:
- [[[prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., ignore_index?],
- [prob_k=1_b=0, tok_0_k=1_b=0, tok_1_k=1_b=0, ..., ignore_index?],
- [...],
- [prob_floor_b=0, ignore_index, ..., ignore_index]],
- [[prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., ignore_index?],
- [prob_k=1_b=1, tok_0_k=1_b=1, tok_1_k=1_b=1, ..., ignore_index?],
- [...],
- [prob_floor_b=1, ignore_index, ..., ignore_index]],
- [...]]
- """
- transformers.set_seed(0)
- transformers.enable_full_determinism(0)
-
- if std_tokenizer is None:
- std_tokenizer = self.std_tokenizer
- token_batch = token_batch.to(self.device)
- tokens = self.token_remap(token_batch, std_tokenizer)
- for k, v in tokens.items():
- if isinstance(v, torch.Tensor):
- tokens[k] = v.to(self.device)
-
- def _forward(_model_output=model_output):
- if _model_output is None:
- _model_output = self.pre_model(input_ids=tokens['input_ids'],
- attention_mask=tokens['attention_mask'],
- output_hidden_states=True)
- self.model_output_check(_model_output)
- # model_output.logits: [batch_size, sequence_len, server_vocab_size]
- last_logits = _model_output.logits[:, -1, :] # [batch_size] server prediction of continuation, right-aligned
-
- # Select topk tokenizer logits and retokenize with std_tokenizer,
- # then compact new token phrases and probabilities into 1-D tensor
- topk_tensor = topk_token_phrases(last_logits, self.tokenizer, topk=topk) # [batch_size, (topk + 1), max_len]
-
- original_loss = self.get_loss_fct(_model_output.logits, tokens['input_ids']).item()
-
- message = f'Loss: {original_loss:.2f}'
-
- _model_output.loss = original_loss
-
- # empty cache to avoid OOM
- torch.cuda.empty_cache()
- return [message, self.munch({}), topk_tensor]
-
- if self.config.neuron.remote_train:
- return _forward() # track gradients for training
-
- with torch.no_grad():
- return _forward() # no gradients
-
- def model_output_check(self, model_output: transformers.modeling_outputs.CausalLMOutputWithPast):
- """
- Verify the model has been ran correctly with valid output.
-
- Args:
- model_output (:obj:`transformers.modeling_outputs.CausalLMOutputWithPast`, required):
- The output of transformers AutoModel.
-
- Returns:
- check_status (:type: `bool`):
- True if the model_output is valid.
- """
- if hasattr(model_output, 'hidden_states') and model_output.hidden_states[-1].isnan().sum() > 0:
- raise ValueError("Got nan value from model last hidden state. If you are using cuda with autocast, try remove setting --neuron.autocast.")
-
- if model_output.logits.isnan().sum() > 0:
- raise ValueError("Got nan value from model logits. If you are using cuda with autocast, try remove setting --neuron.autocast.")
-
- return True
-
- def get_loss_fct(self, logits: torch.FloatTensor, labels: torch.LongTensor) -> torch.FloatTensor:
- """
- Calculate loss_fct, CausalLM loss, next-token prediction loss.
- Args:
- logits (:obj:`torch.FloatTensor`, `required`):
- [batch_size, sequence_len, bittensor.__network_dim__]
- labels (:obj:`torch.LongTensor`, `required`):
- [batch_size, sequence_len]
-
- Returns:
- loss (:obj:`torch.FloatTensor`):
- scalar
- """
- shift_logits = logits[..., :-1, :].contiguous()
- shift_labels = labels[..., 1:].contiguous()
- loss = self.loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
-
- return loss
-
- def check(self):
- r"""Checks the server settings
- """
- assert self.tokenizer.name_or_path == self.pre_model.name_or_path, 'incorrect model ({}) and tokenizer ({})'.format(self.pre_model.name_or_path,self.tokenizer.name_or_path)
- if self.interpolate == False:
- assert self.mapping_function != None, 'Incorrect Settings; needs atleast one mapping function for sequence length changes'
-
- def save(self, path):
- try:
- state_dict = {
- 'model': self.pretrained,
- 'pretrained_model': self.pre_model.state_dict(),
- 'decoder': self.decoder.state_dict(),
- 'best_loss': self.best_loss,
- 'best_remote_loss': self.best_remote_loss,
- }
- if self.padding == False:
- state_dict['mapping'] = self.mapping.state_dict()
- torch.save( state_dict, "{}/model.torch".format( path) )
- bittensor.logging.success(prefix='Saved model', sufix='{}/model.torch'.format( path ) )
- except Exception as e:
- logger.exception('Failed to save model with error:{}', e)
-
- def load(self, path):
- try:
- state_dict= torch.load("{}/model.torch".format( path ))
- if self.pretrained == state_dict['model']:
- self.pre_model.load_state_dict(state_dict['pretrained_model'], strict=False)
- self.decoder.load_state_dict(state_dict['decoder'])
- if self.padding == False:
- self.mapping.load_state_dict(state_dict['mapping'])
- self.best_loss = state_dict['best_loss']
- self.best_remote_loss = state_dict['best_remote_loss']
- bittensor.logging.success( prefix = 'Reloaded model', sufix = '{}/model.torch'.format( path ))
-
-
- except Exception as e:
- logger.warning('No saved model found with error: {}', e)
-
- @staticmethod
- def config ():
- parser = argparse.ArgumentParser()
- parser.add_argument('--config', type=str, help='If set, defaults are overridden by passed file.')
-
- # ML model arguements
- parser.add_argument('--neuron.learning_rate', type=float, help='Training initial learning rate.', default=0.01)
- parser.add_argument('--neuron.momentum', type=float, help='optimizer momentum.', default=0.8)
- parser.add_argument('--neuron.clip_gradients', type=float, help='Implement gradient clipping to avoid exploding loss on smaller architectures.', default=1.0)
- parser.add_argument('--neuron.device', type=str, help='miner default training device cpu/cuda', default=("cuda" if torch.cuda.is_available() else "cpu"))
- parser.add_argument('--neuron.model_name', type=str, help='pretrained model from hugging face',default='gpt2')
- parser.add_argument('--neuron.pretrained', action='store_false', help='if the model should be pretrained',default=True)
- parser.add_argument('--neuron.padding', action='store_false', help='To pad out final dimensions',default=True)
- parser.add_argument('--neuron.interpolate', action='store_false', help='To interpolate between sentence length',default=True)
- parser.add_argument('--neuron.inter_degree', type=str, help='Interpolate algorithm (nearest | linear | bilinear | bicubic | trilinear | area)', default='nearest')
- parser.add_argument('--neuron.autocast', action='store_true', help='(experimental) autocasts the model to float16. Must require cuda', default=True)
- parser.add_argument('--neuron.local_train', action='store_true', help='''If true, allow local training''', default=False)
- parser.add_argument('--neuron.remote_train', action='store_true', help='''If true, allow remote training''', default=False)
- parser.add_argument('--neuron.finetune.all', action='store_true', help='Finetune your whole model instead of only on the last (few) layers', default=False)
- parser.add_argument('--neuron.finetune.num_layers', type=int, help='The number of layers to finetune on your model.', default=1)
- parser.add_argument('--neuron.finetune.layer_name', type=str, help='Specify since which layer to finetune. eg. encoder.layer.11', default=None)
-
- # Miner arguements
- parser.add_argument('--neuron.name', type=str, help='Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name ', default='core_server')
- parser.add_argument('--neuron.checking', action='store_false', help='To check if server settings are correct',default=True)
- parser.add_argument('--neuron.restart', action='store_true', help='If True, train the neuron from the beginning', default=False)
- parser.add_argument('--neuron.no_set_weights', action='store_true', help='If True, the model does not set weights.', default=False)
- parser.add_argument('--neuron.blacklist.stake', type=float, help='Amount of stake (tao) in order not to get blacklisted', default=10)
- parser.add_argument('--neuron.blocks_per_epoch', type=int, help='Blocks per epoch', default=10)
- parser.add_argument('--neuron.blacklist.time', type=int, help='how often a peer can query you (seconds) ', default=1)
- parser.add_argument('--neuron.blocks_per_set_weights', type=float, help='how often to set weights', default=-1)
- parser.add_argument('--neuron.metagraph_sync', type=float, help='how often to sync the metagraph', default=100000)
- parser.add_argument('--neuron.blacklist_allow_non_registered', action='store_true', help='''If true, allow non-registered peers''', default=False)
- parser.add_argument('--neuron.disable_blacklist', action='store_true', help='Turns off blacklisting', default=False)
- parser.add_argument('--neuron.disable_priority', action='store_true', help='Turns off priority threadpool', default=False)
- parser.add_argument('--neuron.num_remote_loss', type=int, help='Number of past remote loss to keep in stat.', default=20)
- parser.add_argument('--neuron.max_batch_size', type=int, help='The maximum batch size for forward requests.', default=-1)
- parser.add_argument('--neuron.max_sequence_len', type=int, help='The maximum sequence length for forward requests.', default=-1)
- parser.add_argument('--neuron.blacklist.hotkeys', type=str, required=False, nargs='*', action='store', help='To blacklist certain hotkeys', default=[])
-
- # Synapse Arguements
- parser.add_argument('--neuron.lasthidden', action='store_false', help='To turn off last hidden synapse', default=True)
- parser.add_argument('--neuron.causallm', action='store_false', help='To turn off causallm synapse', default=True)
- parser.add_argument('--neuron.causallmnext', action='store_false', help='To turn off causallmnext synapse', default=True)
- parser.add_argument('--neuron.seq2seq', action='store_false', help='To turn off seq2seq synapse', default=True)
- parser.add_argument('--neuron.lasthidden_stake', type = float, help='the amount of stake to run last hidden synapse',default=0)
- parser.add_argument('--neuron.causallm_stake', type = float, help='the amount of stake to run causallm synapse',default=0)
- parser.add_argument('--neuron.causallmnext_stake', type=float, help='the amount of stake to run causallmnext synapse', default=0)
- parser.add_argument('--neuron.seq2seq_stake', type = float, help='the amount of stake to run seq2seq synapse',default=0)
-
- # Netuid Arg
- parser.add_argument('--netuid', type=int , help='Subnet netuid', default=1)
-
- bittensor.wallet.add_args( parser )
- bittensor.axon.add_args( parser )
- bittensor.subtensor.add_args( parser )
- bittensor.logging.add_args( parser )
- if hasattr(bittensor, 'wanb'):
- bittensor.wandb.add_args(parser)
- bittensor.prioritythreadpool.add_args( parser )
- bittensor.dataset.add_args( parser )
- if hasattr(bittensor, 'metagraph'):
- if hasattr(bittensor.metagraph, 'add_args'):
- bittensor.metagraph.add_args( parser )
- bittensor.prometheus.add_args( parser )
- return bittensor.config( parser )
-
- @classmethod
- def test(cls):
- dataset = c.module('dataset')
- sample = dataset.sample()
- self = cls()
- sample = self.encode_forward_causallmnext(sample['input_ids'])
- cls.print('passed')
-if __name__ == "__main__":
- r""" Main entry point into the miner CLI.
- """
- server.run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/AI21/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/AI21/README.md
deleted file mode 100644
index cc6a58d43..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/AI21/README.md
+++ /dev/null
@@ -1,114 +0,0 @@
-## AI21 Miner
-AI21 Language Model Serving with BitTensor
-This code is for running a language model powered by AI21 through the BitTensor framework.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/AI21/requirements.txt
-python3 neurons/text/prompting/miners/AI21/miner.py --ai21.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] --ai21.api_key AI21.API_KEY [--ai21.model_name AI21.MODEL_NAME] [--ai21.stop AI21.STOP] [--netuid NETUID]
- [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --ai21.api_key AI21.API_KEY
- AI21 API key.
- --ai21.model_name AI21.MODEL_NAME
- Name of the model.
- --ai21.stop AI21.STOP
- Stop tokens.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/AI21/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/AI21/neuron.py
deleted file mode 100644
index e9f33ae09..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/AI21/neuron.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import bittensor
-
-from typing import List, Dict
-from langchain.llms import AI21
-
-class AI21Miner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- assert config.ai21.api_key != None, 'the miner requires passing --ai21.api_key as an argument of the config.'
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--ai21.api_key', type=str, help='AI21 API key.', required=True)
- parser.add_argument('--ai21.model_name', type=str, help='Name of the model.', default='j2-jumbo-instruct')
- parser.add_argument('--ai21.stop', help='Stop tokens.', default=['user: ', 'bot: ', 'system: '])
-
- def __init__( self ):
- super( AI21Miner, self ).__init__()
- print ( self.config )
-
- bittensor.logging.info( 'Loading AI21 Model...' )
- self.model = AI21(
- model = self.config.ai21.model_name,
- ai21_api_key = self.config.ai21.api_key,
- stop = self.config.ai21.stop
- )
- bittensor.logging.info( 'Model loaded!' )
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- @staticmethod
- def _process_history( history: List[Dict[str, str]] ) -> str:
- processed_history = ''
- for message in history:
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self._process_history(messages)
- resp = self.model(history)
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- AI21Miner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/AI21/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/AI21/requirements.txt
deleted file mode 100644
index e7f08b213..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/AI21/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-langchain
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/README.md
deleted file mode 100644
index da66c18d7..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/README.md
+++ /dev/null
@@ -1,124 +0,0 @@
-## AlephAlpha Miner
-AlephAlpha Language Model Serving with BitTensor
-This code is for running a language model powered by AlephAlpha through the BitTensor framework.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/AlephAlpha/requirements.txt
-python3 neurons/text/prompting/miners/AlephAlpha/miner.py --aleph.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] --aleph.api_key ALEPH.API_KEY [--aleph.model ALEPH.MODEL] [--aleph.maximum_tokens ALEPH.MAXIMUM_TOKENS]
- [--aleph.temperature ALEPH.TEMPERATURE] [--aleph.stop_sequences ALEPH.STOP_SEQUENCES] [--aleph.top_k ALEPH.TOP_K]
- [--aleph.top_p ALEPH.TOP_P] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --aleph.api_key ALEPH.API_KEY
- AlephAlpha API key.
- --aleph.model ALEPH.MODEL
- Model name to use.
- --aleph.maximum_tokens ALEPH.MAXIMUM_TOKENS
- The maximum number of tokens to be generated.
- --aleph.temperature ALEPH.TEMPERATURE
- A non-negative float that tunes the degree of randomness in generation.
- --aleph.stop_sequences ALEPH.STOP_SEQUENCES
- Stop tokens.
- --aleph.top_k ALEPH.TOP_K
- Number of most likely tokens to consider at each step.
- --aleph.top_p ALEPH.TOP_P
- Total probability mass of tokens to consider at each step.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/neuron.py
deleted file mode 100644
index 3ff6519e1..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/neuron.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import bittensor
-from rich import print
-from typing import List, Dict
-
-from langchain.llms import AlephAlpha
-
-class AlephAlphaMiner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- assert config.aleph.api_key != None, 'the miner requires passing --aleph.api_key as an argument of the config.'
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--aleph.api_key', type=str, help='AlephAlpha API key.', required=True)
- parser.add_argument('--aleph.model', type=str, help='Model name to use.', default='luminous-base')
- parser.add_argument('--aleph.maximum_tokens', type=int, help='The maximum number of tokens to be generated.', default=64)
- parser.add_argument('--aleph.temperature', type=float, help='A non-negative float that tunes the degree of randomness in generation.', default=0.0)
- parser.add_argument('--aleph.stop_sequences', type=List[str], help='Stop tokens.', default=['user: ', 'bot: ', 'system: '])
- parser.add_argument('--aleph.top_k', type=int, help='Number of most likely tokens to consider at each step.', default=0)
- parser.add_argument('--aleph.top_p', type=float, help='Total probability mass of tokens to consider at each step.', default=0.0)
-
- def __init__( self ):
- super( AlephAlphaMiner, self ).__init__()
- print ( self.config )
-
- self.model = AlephAlpha(
- aleph_alpha_api_key = self.config.aleph.api_key,
- model = self.config.aleph.model,
- maximum_tokens = self.config.aleph.maximum_tokens,
- temperature = self.config.aleph.temperature,
- top_k = self.config.aleph.top_k,
- top_p = self.config.aleph.top_p,
- stop_sequences = self.config.aleph.stop_sequences
- )
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- @staticmethod
- def _process_history( history: List[Dict[str, str]] ) -> str:
- processed_history = ''
- for message in history:
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- def blacklist(self, forward_call: 'bittensor.BittensorCall' ):
- return False
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- bittensor.logging.info('messages', str(messages))
- history = self._process_history(messages)
- bittensor.logging.info('history', str(history))
- resp = self.model(history)
- bittensor.logging.info('response', str(resp))
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- AlephAlphaMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/requiremenets.txt b/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/requiremenets.txt
deleted file mode 100644
index 110dc27b2..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/AlephAlpha/requiremenets.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-aleph_alpha_client
-langchain
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/cerebras/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/cerebras/README.md
deleted file mode 100644
index 5bb5f5250..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/cerebras/README.md
+++ /dev/null
@@ -1,117 +0,0 @@
-## Cerebras Miner
-Cerebras 13B Language Model Serving with BitTensor
-This code is for running a language model powered by Cerebrus through the BitTensor framework.
-
-# Example Usage
-```
-python3 neurons/text/prompting/miners/cerebras/neuron.py
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--cerebras.device CEREBRAS.DEVICE] [--cerebras.max_length CEREBRAS.MAX_LENGTH] [--cerebras.do_sample]
- [--cerebras.no_repeat_ngram_size CEREBRAS.NO_REPEAT_NGRAM_SIZE] [--cerebras.model_size {1.3B,2.7B,6.7B,13B}]
- [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --cerebras.device CEREBRAS.DEVICE
- Device to load model
- --cerebras.max_length CEREBRAS.MAX_LENGTH
- The maximum length (in tokens) of the generated text.
- --cerebras.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --cerebras.no_repeat_ngram_size CEREBRAS.NO_REPEAT_NGRAM_SIZE
- The size of the n-grams to avoid repeating in the generated text.
- --cerebras.model_size {1.3B,2.7B,6.7B,13B}
- Model size to use.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/cerebras/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/cerebras/neuron.py
deleted file mode 100644
index 714c3baac..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/cerebras/neuron.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-# General.
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
-
-class CerebrasMiner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- pass
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--cerebras.device', type=str, help='Device to load model', default="cuda")
- parser.add_argument('--cerebras.max_length', type=int, default=50, help='The maximum length (in tokens) of the generated text.')
- parser.add_argument('--cerebras.do_sample', action='store_true', default=False, help='Whether to use sampling or not (if not, uses greedy decoding).')
- parser.add_argument('--cerebras.no_repeat_ngram_size', type=int, default=2, help='The size of the n-grams to avoid repeating in the generated text.')
- parser.add_argument('--cerebras.model_size', type=str, choices=['1.3B', '2.7B', '6.7B', '13B'], default="1.3B", help='Model size to use.')
-
- def __init__( self ):
- super( CerebrasMiner, self ).__init__()
- print ( self.config )
-
- bittensor.logging.info( "Loading Cerebras GPT {} model...".format( self.config.cerebras.model_size) )
- model = AutoModelForCausalLM.from_pretrained( "cerebras/Cerebras-GPT-{}".format( self.config.cerebras.model_size) )
- tokenizer = AutoTokenizer.from_pretrained( "cerebras/Cerebras-GPT-{}".format( self.config.cerebras.model_size) )
-
- self.pipe = pipeline(
- "text-generation",
- model = model,
- tokenizer = tokenizer,
- device = 0,
- do_sample = False,
- max_new_tokens = self.config.cerebras.max_length,
- no_repeat_ngram_size = self.config.cerebras.no_repeat_ngram_size
- )
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- @staticmethod
- def _process_history( history: List[Dict[str, str]] ) -> str:
- processed_history = ''
- for message in history:
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self._process_history(messages)
- return self.pipe( history )[0]['generated_text'].split(':')[-1].replace( str( history ), "")
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- CerebrasMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/cohere/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/cohere/README.md
deleted file mode 100644
index 03f971646..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/cohere/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-# Cohere Miner
-This repository contains the implementation of a language model server using the Cohere API. The model is integrated into the Bittensor network, allowing it to serve as a Bittensor neuron.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/cohere/requirements.txt
-python3 neurons/text/prompting/miners/cohere/neuron.py --cohere.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--cohere.model_name COHERE.MODEL_NAME] [--cohere.max_tokens COHERE.MAX_TOKENS]
- [--cohere.temperature COHERE.TEMPERATURE] [--cohere.k COHERE.K] [--cohere.p COHERE.P]
- [--cohere.frequency_penalty COHERE.FREQUENCY_PENALTY] [--cohere.presence_penalty COHERE.PRESENCE_PENALTY]
- [--cohere.truncate COHERE.TRUNCATE] [--cohere.stop COHERE.STOP] --cohere.api_key COHERE.API_KEY [--netuid NETUID]
- [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --cohere.model_name COHERE.MODEL_NAME
- Name of the model.
- --cohere.max_tokens COHERE.MAX_TOKENS
- Number of tokens to generate.
- --cohere.temperature COHERE.TEMPERATURE
- Temperature of generation.
- --cohere.k COHERE.K Number of most likely tokens to consider at each step.
- --cohere.p COHERE.P Total probability mass of tokens to consider at each step.
- --cohere.frequency_penalty COHERE.FREQUENCY_PENALTY
- Penalizes repeated tokens according to frequency.
- --cohere.presence_penalty COHERE.PRESENCE_PENALTY
- Penalizes repeated tokens.
- --cohere.truncate COHERE.TRUNCATE
- Specify how the client handles inputs longer than the maximum token length: Truncate from START, END or NONE
- --cohere.stop COHERE.STOP
- List of tokens to stop generation on.
- --cohere.api_key COHERE.API_KEY
- API key for Cohere.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/cohere/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/cohere/neuron.py
deleted file mode 100644
index a4a143313..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/cohere/neuron.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-# General.
-import json
-import argparse
-import bittensor
-from typing import List, Dict
-from langchain.llms import Cohere
-
-class CohereMiner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- assert config.cohere.api_key != None, 'the miner requires passing --cohere.api_key as an argument of the config.'
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--cohere.model_name', type=str, help='Name of the model.', default='command-xlarge-nightly')
- parser.add_argument('--cohere.max_tokens', type=int, help='Number of tokens to generate.', default=256)
- parser.add_argument('--cohere.temperature', type=float, help='Temperature of generation.', default=0.75)
- parser.add_argument('--cohere.k', type=int, help='Number of most likely tokens to consider at each step.', default=0)
- parser.add_argument('--cohere.p', type=int, help='Total probability mass of tokens to consider at each step.', default=1)
- parser.add_argument('--cohere.frequency_penalty', type=float, help='Penalizes repeated tokens according to frequency.', default=0.0)
- parser.add_argument('--cohere.presence_penalty', type=float, help='Penalizes repeated tokens.', default=0.0)
- parser.add_argument('--cohere.truncate', type=str, help='Specify how the client handles inputs longer than the maximum token length: Truncate from START, END or NONE', default=None)
- parser.add_argument('--cohere.stop', type=str, help='List of tokens to stop generation on.', default=None)
- parser.add_argument('--cohere.api_key', type=str, help='API key for Cohere.', required=True)
-
- def __init__( self ):
- super( CohereMiner, self ).__init__()
- print ( self.config )
-
- self.model = Cohere(
- model=self.config.cohere.model_name,
- cohere_api_key=self.config.cohere.api_key,
- max_tokens=self.config.cohere.max_tokens,
- temperature=self.config.cohere.temperature,
- k=self.config.cohere.k,
- p=self.config.cohere.p,
- frequency_penalty=self.config.cohere.frequency_penalty,
- presence_penalty=self.config.cohere.presence_penalty,
- truncate=self.config.cohere.truncate,
- stop=self.config.cohere.stop,
- )
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- @staticmethod
- def _process_history( history: List[Dict[str, str]] ) -> str:
- processed_history = ''
- for message in history:
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self._process_history( messages )
- return self.model( history )
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- CohereMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/cohere/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/cohere/requirements.txt
deleted file mode 100644
index 889f2e0a9..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/cohere/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-cohere
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/commune/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/commune/README.md
deleted file mode 100644
index c7b6ee866..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/commune/README.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# OpenAI Bittensor Miner
-This repository contains a Bittensor Miner that uses OpenAI's GPT-3.5-turbo model as its synapse. The miner connects to the Bittensor network, registers its wallet, and serves the GPT-3.5-turbo model to the network.
-
-## Prerequisites
-
-- Python 3.8+
-- OpenAI Python API (https://github.com/openai/openai)
-
-## Installation
-
-1. Clone the repository
-2. Install the required packages with `pip install -r requirements.txt`
-3. Set your OpenAI API key in the `api_key` argument when running the script
-
-For more configuration options related to the wallet, axon, subtensor, logging, and metagraph, please refer to the Bittensor documentation.
-
-## Example Usage
-
-To run the OpenAI Bittensor Miner with default settings, use the following command:
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/openai/requirements.txt
-python3 neurons/text/prompting/miners/openai/neuron.py --openai.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--openai.api_key OPENAI.API_KEY] [--openai.suffix OPENAI.SUFFIX] [--openai.max_tokens OPENAI.MAX_TOKENS]
- [--openai.temperature OPENAI.TEMPERATURE] [--openai.top_p OPENAI.TOP_P] [--openai.n OPENAI.N]
- [--openai.presence_penalty OPENAI.PRESENCE_PENALTY] [--openai.frequency_penalty OPENAI.FREQUENCY_PENALTY]
- [--openai.model_name OPENAI.MODEL_NAME] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --openai.api_key OPENAI.API_KEY
- openai api key
- --openai.suffix OPENAI.SUFFIX
- The suffix that comes after a completion of inserted text.
- --openai.max_tokens OPENAI.MAX_TOKENS
- The maximum number of tokens to generate in the completion.
- --openai.temperature OPENAI.TEMPERATURE
- Sampling temperature to use, between 0 and 2.
- --openai.top_p OPENAI.TOP_P
- Nucleus sampling parameter, top_p probability mass.
- --openai.n OPENAI.N How many completions to generate for each prompt.
- --openai.presence_penalty OPENAI.PRESENCE_PENALTY
- Penalty for tokens based on their presence in the text so far.
- --openai.frequency_penalty OPENAI.FREQUENCY_PENALTY
- Penalty for tokens based on their frequency in the text so far.
- --openai.model_name OPENAI.MODEL_NAME
- OpenAI model to use for completion.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/commune/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/commune/neuron.py
deleted file mode 100644
index 670ee44bf..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/commune/neuron.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# The MIT License (MIT)
-# Copyright 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the Software), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import openai
-import argparse
-import bittensor
-from typing import List, Dict
-
-class MaoMiner( bittensor.BasePromptingMiner ):
-
- def __init__( self , config):
- super( MaoMiner, self ).__init__(config=config)
- openai.api_key = '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'
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- pass
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--openai.api_key', type=str, default='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', help='openai api key')
- parser.add_argument('--openai.suffix', type=str, default=None, help="The suffix that comes after a completion of inserted text.")
- parser.add_argument('--openai.max_tokens', type=int, default=256, help="The maximum number of tokens to generate in the completion.")
- parser.add_argument('--openai.temperature', type=float, default=0.7, help="Sampling temperature to use, between 0 and 2.")
- parser.add_argument('--openai.top_p', type=float, default=1, help="Nucleus sampling parameter, top_p probability mass.")
- parser.add_argument('--openai.n', type=int, default=1, help="How many completions to generate for each prompt.")
- parser.add_argument('--openai.presence_penalty', type=float, default=0, help="Penalty for tokens based on their presence in the text so far.")
- parser.add_argument('--openai.frequency_penalty', type=float, default=0, help="Penalty for tokens based on their frequency in the text so far.")
- parser.add_argument('--openai.model_name', type=str, default='gpt-3.5-turbo', help="OpenAI model to use for completion.")
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- resp = openai.ChatCompletion.create(
- model = self.config.openai.model_name,
- messages = messages,
- temperature = self.config.openai.temperature,
- max_tokens = self.config.openai.max_tokens,
- top_p = self.config.openai.top_p,
- frequency_penalty = self.config.openai.frequency_penalty,
- presence_penalty = self.config.openai.presence_penalty,
- n = self.config.openai.n,
- )['choices'][0]['message']['content']
-
- print("Prompt : ")
- print(messages[-100:])
- print("Response Openai : ")
- print(resp)
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- MaoMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/commune/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/commune/requirements.txt
deleted file mode 100644
index f0dd0aec5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/commune/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-openai
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/README.md
deleted file mode 100644
index 55c4ae8e4..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/README.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# GooseAI Bittensor Miner
-This repository contains a Bittensor Miner that uses GooseAI's endpoint. The miner connects to the Bittensor network, registers its wallet, and serves a GooseAI model to the network.
-
-## Prerequisites
-
-- Python 3.8+
-- langchain
-
-## Installation
-
-1. Clone the repository
-2. Install the required packages with `pip install -r requirements.txt`
-3. Set your GooseAI API key in the `api_key` argument when running the script
-
-For more configuration options related to the wallet, axon, subtensor, logging, and metagraph, please refer to the Bittensor documentation.
-
-## Example Usage
-
-To run the GooseAI Bittensor Miner with default settings, use the following command:
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/gooseai/requirements.txt
-python3 neurons/text/prompting/miners/gooseai/neuron.py --gooseai.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] --gooseai.api_key GOOSEAI.API_KEY [--gooseai.model_name GOOSEAI.MODEL_NAME]
- [--gooseai.temperature GOOSEAI.TEMPERATURE] [--gooseai.max_tokens GOOSEAI.MAX_TOKENS] [--gooseai.top_p GOOSEAI.TOP_P]
- [--gooseai.min_tokens GOOSEAI.MIN_TOKENS] [--gooseai.frequency_penalty GOOSEAI.FREQUENCY_PENALTY]
- [--gooseai.presence_penalty GOOSEAI.PRESENCE_PENALTY] [--gooseai.n GOOSEAI.N] [--gooseai.model_kwargs GOOSEAI.MODEL_KWARGS]
- [--gooseai.logit_bias GOOSEAI.LOGIT_BIAS] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --gooseai.api_key GOOSEAI.API_KEY
- GooseAI api key required.
- --gooseai.model_name GOOSEAI.MODEL_NAME
- Model name to use
- --gooseai.temperature GOOSEAI.TEMPERATURE
- What sampling temperature to use
- --gooseai.max_tokens GOOSEAI.MAX_TOKENS
- The maximum number of tokens to generate in the completion
- --gooseai.top_p GOOSEAI.TOP_P
- Total probability mass of tokens to consider at each step
- --gooseai.min_tokens GOOSEAI.MIN_TOKENS
- The minimum number of tokens to generate in the completion
- --gooseai.frequency_penalty GOOSEAI.FREQUENCY_PENALTY
- Penalizes repeated tokens according to frequency
- --gooseai.presence_penalty GOOSEAI.PRESENCE_PENALTY
- Penalizes repeated tokens
- --gooseai.n GOOSEAI.N
- How many completions to generate for each prompt
- --gooseai.model_kwargs GOOSEAI.MODEL_KWARGS
- Holds any model parameters valid for `create` call not explicitly specified
- --gooseai.logit_bias GOOSEAI.LOGIT_BIAS
- Adjust the probability of specific tokens being generated
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/neuron.py
deleted file mode 100644
index 6e633d2e9..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/neuron.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import bittensor
-from typing import List, Dict, Any, Optional
-from langchain.llms import GooseAI
-
-class GooseAIMiner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ): pass
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument("--gooseai.api_key", type=str, required=True, help="GooseAI api key required.")
- parser.add_argument("--gooseai.model_name", type=str, default="gpt-neo-20b", help="Model name to use")
- parser.add_argument("--gooseai.temperature", type=float, default=0.7, help="What sampling temperature to use")
- parser.add_argument("--gooseai.max_tokens", type=int, default=256, help="The maximum number of tokens to generate in the completion")
- parser.add_argument("--gooseai.top_p", type=float, default=1, help="Total probability mass of tokens to consider at each step")
- parser.add_argument("--gooseai.min_tokens", type=int, default=1, help="The minimum number of tokens to generate in the completion")
- parser.add_argument("--gooseai.frequency_penalty", type=float, default=0, help="Penalizes repeated tokens according to frequency")
- parser.add_argument("--gooseai.presence_penalty", type=float, default=0, help="Penalizes repeated tokens")
- parser.add_argument("--gooseai.n", type=int, default=1, help="How many completions to generate for each prompt")
- parser.add_argument("--gooseai.model_kwargs", type=Dict[str, Any], default=dict(), help="Holds any model parameters valid for `create` call not explicitly specified")
- parser.add_argument("--gooseai.logit_bias", type=Optional[Dict[str, float]], default=dict(), help="Adjust the probability of specific tokens being generated")
-
-
- def __init__( self ):
- super( GooseAIMiner, self ).__init__()
- print ( self.config )
- model_kwargs = {
- 'model': self.config.gooseai.model_name,
- 'n_ctx': self.config.gooseai.max_tokens,
- 'n_parts': self.config.gooseai.n,
- 'temp': self.config.gooseai.temperature,
- 'top_p': self.config.gooseai.top_p,
- 'repeat_penalty': self.config.gooseai.frequency_penalty,
- }
- self.model = GooseAI(gooseai_api_key=self.config.gooseai.api_key, model_kwargs=model_kwargs)
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- @staticmethod
- def _process_history(history: List[dict]) -> str:
- processed_history = ''
- for message in history:
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- bittensor.logging.info( 'messages', str( messages ) )
- history = self._process_history( messages )
- bittensor.logging.info( 'history', str( history ) )
- resp = self.model( history )
- bittensor.logging.info('response', str( resp ))
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- GooseAIMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/requirements.txt
deleted file mode 100644
index e7f08b213..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/gooseai/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-langchain
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/README.md
deleted file mode 100644
index c9c876d54..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/README.md
+++ /dev/null
@@ -1,162 +0,0 @@
-## GPT4ALL Miner
-GPT4ALL prompting miner for bittensor
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/gpt4all/requirements.txt
-python3 neurons/text/prompting/miners/gpt4all/neuron.py
-```
-
-# Obtaining (converted) [GPT4All](https://github.com/nomic-ai/gpt4all) weights
-
-- Obtain the `gpt4all-lora-quantized.bin` model
-- It is distributed in the old `ggml` format which is now obsoleted
-- You have to convert it to the new format using [./convert-gpt4all-to-ggml.py](https://github.com/ggerganov/llama.cpp/blob/master/convert-gpt4all-to-ggml.py). You may also need to
-convert the model from the old format to the new format with [./migrate-ggml-2023-03-30-pr613.py](https://github.com/ggerganov/llama.cpp/blob/master/migrate-ggml-2023-03-30-pr613.py):
-
- ```bash
- python3 convert-gpt4all-to-ggml.py models/gpt4all-7B/gpt4all-lora-quantized.bin ./models/tokenizer.model
- python3 migrate-ggml-2023-03-30-pr613.py models/gpt4all-7B/gpt4all-lora-quantized.bin models/gpt4all-7B/gpt4all-lora-quantized-new.bin
- ```
-
-- You can now use the newly generated `gpt4all-lora-quantized-new.bin` model in exactly the same way as all other models
-- The original model is saved in the same folder with a suffix `.orig`
-- Tokenizer can be found [here](https://huggingface.co/decapoda-research/llama-7b-hf/blob/main/tokenizer.model)
-
-
-# Full Usage
-```
-usage: neuron.py [-h] --gpt4all.model GPT4ALL.MODEL [--gpt4all.n_ctx GPT4ALL.N_CTX] [--gpt4all.n_parts GPT4ALL.N_PARTS]
- [--gpt4all.seed GPT4ALL.SEED] [--gpt4all.f16_kv] [--gpt4all.logits_all] [--gpt4all.vocab_only] [--gpt4all.use_mlock]
- [--gpt4all.embedding] [--gpt4all.n_threads GPT4ALL.N_THREADS] [--gpt4all.n_predict GPT4ALL.N_PREDICT]
- [--gpt4all.temp GPT4ALL.TEMP] [--gpt4all.top_p GPT4ALL.TOP_P] [--gpt4all.top_k GPT4ALL.TOP_K] [--gpt4all.echo]
- [--gpt4all.stop GPT4ALL.STOP] [--gpt4all.repeat_last_n GPT4ALL.REPEAT_LAST_N]
- [--gpt4all.repeat_penalty GPT4ALL.REPEAT_PENALTY] [--gpt4all.n_batch GPT4ALL.N_BATCH] [--gpt4all.streaming]
- [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --gpt4all.model GPT4ALL.MODEL
- Path to pretrained gpt4all model in ggml format.
- --gpt4all.n_ctx GPT4ALL.N_CTX
- Token context window.
- --gpt4all.n_parts GPT4ALL.N_PARTS
- Number of parts to split the model into. If -1, the number of parts is automatically determined.
- --gpt4all.seed GPT4ALL.SEED
- Seed. If -1, a random seed is used.
- --gpt4all.f16_kv Use half-precision for key/value cache.
- --gpt4all.logits_all Return logits for all tokens, not just the last token.
- --gpt4all.vocab_only Only load the vocabulary, no weights.
- --gpt4all.use_mlock Force system to keep model in RAM.
- --gpt4all.embedding Use embedding mode only.
- --gpt4all.n_threads GPT4ALL.N_THREADS
- Number of threads to use.
- --gpt4all.n_predict GPT4ALL.N_PREDICT
- The maximum number of tokens to generate.
- --gpt4all.temp GPT4ALL.TEMP
- The temperature to use for sampling.
- --gpt4all.top_p GPT4ALL.TOP_P
- The top-p value to use for sampling.
- --gpt4all.top_k GPT4ALL.TOP_K
- The top-k value to use for sampling.
- --gpt4all.echo Whether to echo the prompt.
- --gpt4all.stop GPT4ALL.STOP
- Stop tokens.
- --gpt4all.repeat_last_n GPT4ALL.REPEAT_LAST_N
- Last n tokens to penalize.
- --gpt4all.repeat_penalty GPT4ALL.REPEAT_PENALTY
- The penalty to apply to repeated tokens.
- --gpt4all.n_batch GPT4ALL.N_BATCH
- Batch size for prompt processing.
- --gpt4all.streaming Whether to stream the results or not.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/neuron.py
deleted file mode 100644
index 3408c7ee5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/neuron.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import bittensor
-from typing import List, Dict
-from langchain.llms import GPT4All
-
-class GPT4ALLMiner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ): pass
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--gpt4all.model', type=str, help='Path to pretrained gpt4all model in ggml format.', required=True)
- parser.add_argument('--gpt4all.n_ctx', type=int, default=512, help='Token context window.')
- parser.add_argument('--gpt4all.n_parts', type=int, default=-1, help='Number of parts to split the model into. If -1, the number of parts is automatically determined.')
- parser.add_argument('--gpt4all.seed', type=int, default=0, help='Seed. If -1, a random seed is used.')
- parser.add_argument('--gpt4all.f16_kv', action='store_true', default=False, help='Use half-precision for key/value cache.')
- parser.add_argument('--gpt4all.logits_all', action='store_true', default=False, help='Return logits for all tokens, not just the last token.')
- parser.add_argument('--gpt4all.vocab_only', action='store_true', default=False, help='Only load the vocabulary, no weights.')
- parser.add_argument('--gpt4all.use_mlock', action='store_true', default=False, help='Force system to keep model in RAM.')
- parser.add_argument('--gpt4all.embedding', action='store_true', default=False, help='Use embedding mode only.')
- parser.add_argument('--gpt4all.n_threads', type=int, default=4, help='Number of threads to use.')
- parser.add_argument('--gpt4all.n_predict', type=int, default=256, help='The maximum number of tokens to generate.')
- parser.add_argument('--gpt4all.temp', type=float, default=0.8, help='The temperature to use for sampling.')
- parser.add_argument('--gpt4all.top_p', type=float, default=0.95, help='The top-p value to use for sampling.')
- parser.add_argument('--gpt4all.top_k', type=int, default=40, help='The top-k value to use for sampling.')
- parser.add_argument('--gpt4all.echo', action='store_true', default=False, help='Whether to echo the prompt.')
- parser.add_argument('--gpt4all.repeat_last_n', type=int, default=64, help='Last n tokens to penalize.')
- parser.add_argument('--gpt4all.repeat_penalty', type=float, default=1.3, help='The penalty to apply to repeated tokens.')
- parser.add_argument('--gpt4all.n_batch', type=int, default=1, help='Batch size for prompt processing.')
- parser.add_argument('--gpt4all.streaming', action='store_true', default=False, help='Whether to stream the results or not.')
-
- def __init__( self ):
- super( GPT4ALLMiner, self ).__init__()
- print ( self.config )
- self.model = GPT4All(
- model=self.config.gpt4all.model,
- n_ctx=self.config.gpt4all.n_ctx,
- n_parts=self.config.gpt4all.n_parts,
- seed=self.config.gpt4all.seed,
- f16_kv=self.config.gpt4all.f16_kv,
- logits_all=self.config.gpt4all.logits_all,
- vocab_only=self.config.gpt4all.vocab_only,
- use_mlock=self.config.gpt4all.use_mlock,
- embedding=self.config.gpt4all.embedding,
- n_threads=self.config.gpt4all.n_threads,
- n_predict=self.config.gpt4all.n_predict,
- temp=self.config.gpt4all.temp,
- top_p=self.config.gpt4all.top_p,
- top_k=self.config.gpt4all.top_k,
- echo=self.config.gpt4all.echo,
- stop=['user: ', 'bot: ', 'system: '],
- repeat_last_n=self.config.gpt4all.repeat_last_n,
- repeat_penalty=self.config.gpt4all.repeat_penalty,
- n_batch=self.config.gpt4all.n_batch,
- streaming=self.config.gpt4all.streaming,
- )
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- @staticmethod
- def _process_history(history: List[dict]) -> str:
- processed_history = ''
- for message in history:
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- bittensor.logging.info( 'messages', str( messages ) )
- history = self._process_history( messages )
- bittensor.logging.info( 'history', str( history ) )
- resp = self.model( history )
- bittensor.logging.info('response', str( resp ))
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- GPT4ALLMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/requirements.txt
deleted file mode 100644
index 8e3ed575c..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/gpt4all/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-langchain
-pyllamacpp
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/README.md
deleted file mode 100644
index 7d22d1188..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/README.md
+++ /dev/null
@@ -1,104 +0,0 @@
-## ChatGLM Miner
- THUDM/chatglm-6b Language Model Serving with BitTensor
- This code is for running a language model powered by ChatGLM through the BitTensor framework.
-
- # Example Usage
- ```
- python3 -m pip install -r neurons/text/prompting/miners/huggingface/chat_glm/requirements.txt
- python3 neurons/text/prompting/miners/huggingface/chat_glm/neuron.py
- ```
-
- # Full Usage
- ```
- usage: neuron.py [-h] [--chat_glm.device CHAT_GLM.DEVICE] [--chat_glm.max_new_tokens CHAT_GLM.MAX_NEW_TOKENS] [--chat_glm.temperature CHAT_GLM.TEMPERATURE] [--chat_glm.do_sample]
- [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN] [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT]
- [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place] [--subtensor.register.verbose]
- [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
- optional arguments:
- -h, --help show this help message and exit
- --chat_glm.device CHAT_GLM.DEVICE
- Device to load model
- --chat_glm.max_new_tokens CHAT_GLM.MAX_NEW_TOKENS
- Max tokens for model output.
- --chat_glm.temperature CHAT_GLM.TEMPERATURE
- Sampling temperature of model
- --chat_glm.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests
- up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for
- testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/neuron.py
deleted file mode 100644
index 23136e752..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/neuron.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModel
-
-class ChatGLMMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = 'chat_glm'
- assistant_label: str = ''
- user_label: str = ''
- system_label: str = ''
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( "THUDM/chatglm-6b", trust_remote_code=True)
-
- def load_model( self ):
- return AutoModel.from_pretrained( "THUDM/chatglm-6b",trust_remote_code=True, torch_dtype = torch.float16 )
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
- history = self.process_history( messages )
- prompt = history[-1][-1]
- if len(history) == 1:
- history = []
- generation, history = self.model.chat(
- self.tokenizer,
- prompt,
- history,
- max_length=self.config.chat_glm.max_new_tokens,
- temperature=self.config.chat_glm.temperature,
- do_sample=self.config.chat_glm.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
-
- bittensor.logging.debug("Message: " + str( messages ).replace( "<","-" ).replace( ">","-" ) )
- bittensor.logging.debug("Generation: " + str( generation ).replace( "<","-" ).replace( ">","-" ) )
- return generation
-
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- ChatGLMMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/requirements.txt
deleted file mode 100644
index bb07cd001..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/chat_glm/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-protobuf==3.20.0
-transformers==4.27.1
-icetk
-cpm_kernels
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/README.md
deleted file mode 100644
index 724506535..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/README.md
+++ /dev/null
@@ -1,114 +0,0 @@
-
-## Databricks Dolly 3B/12B Miner
-Dolyl 3B and 12B completion miner for bittensor's prompting network.
-
-# Example Usage
-```
-python3 neurons/text/prompting/miners/huggingface/dolly/neuron.py --dolly.model_name databricks/dolly-v2-12b
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--dolly.model_name DOLLY.MODEL_NAME] [--dolly.device DOLLY.DEVICE] [--dolly.max_new_tokens DOLLY.MAX_NEW_TOKENS] [--dolly.temperature DOLLY.TEMPERATURE]
- [--dolly.do_sample] [--dolly.do_prompt_injection] [--dolly.system_prompt DOLLY.SYSTEM_PROMPT] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE]
- [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN] [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT]
- [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL]
- [--subtensor.register.no_output_in_place] [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]] [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB]
- [--logging.debug] [--logging.trace] [--logging.record_log] [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --dolly.model_name DOLLY.MODEL_NAME
- Name/path of model to load
- --dolly.device DOLLY.DEVICE
- Device to load model
- --dolly.max_new_tokens DOLLY.MAX_NEW_TOKENS
- Max tokens for model output.
- --dolly.temperature DOLLY.TEMPERATURE
- Sampling temperature of model
- --dolly.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --dolly.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --dolly.system_prompt DOLLY.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up to
- this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for testing))
- If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/neuron.py
deleted file mode 100644
index 52797011d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/neuron.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import pipeline
-
-
-class Dolly12BMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = "dolly"
- assistant_label: str = "### Response:"
- user_label: str = "### Instruction:"
- system_label: str = ""
-
- def load_model( self ):
- bittensor.logging.info( 'Loading ' + str( self.config.dolly.model_name ) )
- model = pipeline( model=self.config.dolly.model_name, torch_dtype=torch.bfloat16, trust_remote_code=True, device=0 )
- bittensor.logging.info( 'Model loaded!' )
- return model
-
- def load_tokenizer( self ):
- pass
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
-
- history = self.process_history( messages )
- prompt = history + self.assistant_label
- generation = self.model( prompt )
-
- bittensor.logging.debug(" Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- Dolly12BMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/requirements.txt
deleted file mode 100644
index fe2343560..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dolly/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-accelerate>=0.16.0,<1
-transformers[torch]>=4.28.1,<5
-torch>=1.13.1,<2"
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dromedary/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dromedary/README.md
deleted file mode 100644
index c526dac85..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dromedary/README.md
+++ /dev/null
@@ -1,116 +0,0 @@
-
-## Dromedary Miner
-Dromedary 65B completion miner for bittensor's prompting network.
-
-# Example Usage
-```
-python3 neurons/text/prompting/miners/huggingface/dromedary/neuron.py
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--dromedary.model_name DROMEDARY.MODEL_NAME] [--dromedary.device DROMEDARY.DEVICE] [--dromedary.max_new_tokens DROMEDARY.MAX_NEW_TOKENS]
- [--dromedary.temperature DROMEDARY.TEMPERATURE] [--dromedary.do_sample] [--dromedary.do_prompt_injection] [--dromedary.system_prompt DROMEDARY.SYSTEM_PROMPT]
- [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME]
- [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT]
- [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL]
- [--subtensor.register.no_output_in_place] [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]] [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB]
- [--logging.debug] [--logging.trace] [--logging.record_log] [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --dromedary.model_name DROMEDARY.MODEL_NAME
- Name/path of model to load
- --dromedary.device DROMEDARY.DEVICE
- Device to load model
- --dromedary.max_new_tokens DROMEDARY.MAX_NEW_TOKENS
- Max tokens for model output.
- --dromedary.temperature DROMEDARY.TEMPERATURE
- Sampling temperature of model
- --dromedary.do_sample
- Whether to use sampling or not (if not, uses greedy decoding).
- --dromedary.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --dromedary.system_prompt DROMEDARY.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up
- to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for
- testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dromedary/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dromedary/neuron.py
deleted file mode 100644
index 21ec14f75..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/dromedary/neuron.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-
-class DromedaryMiner( bittensor.HuggingFaceMiner ):
- arg_prefix: str = "dromedary"
- assistant_label: str = "Dromedary:"
- user_label: str = "User:"
- system_label: str = "System:"
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument( '--dromedary.device_map', type=str, help='Device to load model: Default "auto" for multi-GPU', default="auto" )
-
- def __init__( self ):
- super( DromedaryMiner, self ).__init__()
- print ( self.config )
-
- bittensor.logging.info( 'Loading ' + str( self.config.dromedary.model_name ) )
- self.tokenizer = AutoTokenizer.from_pretrained( self.config.dromedary.model_name, use_fast=False )
- self.model = AutoModelForCausalLM.from_pretrained(
- self.config.dromedary.model_name,
- device_map=self.config.dromedary.device_map,
- torch_dtype=torch.float16,
- low_cpu_mem_usage=True
- )
- bittensor.logging.info( 'Model loaded!' )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
-
- history = self._process_history( self, messages )
- prompt = history + self.assistant_label
-
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.dromedary.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.dromedary.max_new_tokens,
- temperature=self.config.dromedary.temperature,
- do_sample=self.config.dromedary.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- DromedaryMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/fastchat_t5/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/fastchat_t5/README.md
deleted file mode 100644
index d74449977..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/fastchat_t5/README.md
+++ /dev/null
@@ -1,127 +0,0 @@
-# FastChat T5 Miner
-FastChat T5 completion miner for bittensor's prompting network.
-
-# Download weights
-They disabled API inference requests via HuggingFace so you've gotta do it yourself by downloading the weights and passing the path directly.
-
-```bash
-git lfs install
-git clone https://huggingface.co/lmsys/fastchat-t5-3b-v1.0
-```
-
-# Example Usage
-```
-python3 neurons/text/prompting/miners/huggingface/fastchat_t5/neuron.py --fastchat_t5.model_path /path/to/fastchat-t5-3b-v1.0
-```
-
-# Full Usage
-```
-usage: fastchat-t5.py [-h] [--fastchat_t5.MODEL_PATH FASTCHAT_T5.MODEL_PATH] [--fastchat_t5.device FASTCHAT_T5.DEVICE] [--fastchat_t5.max_new_tokens FASTCHAT_T5.MAX_NEW_TOKENS]
- [--fastchat_t5.temperature FASTCHAT_T5.TEMPERATURE] [--fastchat_t5.greedy_decoding] [--fastchat_t5.repetition_penalty FASTCHAT_T5.REPETITION_PENALTY]
- [--fastchat_t5.do_prompt_injection] [--fastchat_t5.system_prompt FASTCHAT_T5.SYSTEM_PROMPT] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE]
- [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN] [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE]
- [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE]
- [--axon.port AXON.PORT] [--axon.ip AXON.IP] [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP]
- [--axon.max_workers AXON.MAX_WORKERS] [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place] [--subtensor.register.verbose]
- [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --fastchat_t5.MODEL_PATH FASTCHAT_T5.MODEL_PATH
- Name/path of model to load
- --fastchat_t5.device FASTCHAT_T5.DEVICE
- Device to load model
- --fastchat_t5.max_new_tokens FASTCHAT_T5.MAX_NEW_TOKENS
- Max tokens for model output.
- --fastchat_t5.temperature FASTCHAT_T5.TEMPERATURE
- Sampling temperature of model
- --fastchat_t5.greedy_decoding
- Whether to use greedy sampling or not (if not, uses multinomial sampling).
- --fastchat_t5.repetition_penalty FASTCHAT_T5.REPETITION_PENALTY
- Repetition penalty for model
- --fastchat_t5.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --fastchat_t5.system_prompt FASTCHAT_T5.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up
- to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for
- testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/fastchat_t5/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/fastchat_t5/neuron.py
deleted file mode 100644
index 4bc47638b..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/fastchat_t5/neuron.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import torch
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import T5Tokenizer, AutoModelForSeq2SeqLM
-
-class FastChatT5Miner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = "fastchat_t5"
- assistant_label: str = "ASSISTANT:"
- user_label: str = "USER:"
- system_label: str = "SYSTEM:"
-
- def load_model( self ):
- bittensor.logging.info( 'Loading ' + str( self.config.fastchat_t5.model_name ) )
- model = AutoModelForSeq2SeqLM.from_pretrained( self.config.fastchat_t5.model_name, local_files_only=True, low_cpu_mem_usage=True, torch_dtype=torch.float16 )
- bittensor.logging.info( 'Model loaded!' )
- return model
-
- def load_tokenizer( self ):
- return T5Tokenizer.from_pretrained( self.config.fastchat_t5.model_name, local_files_only=True )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self.process_history( messages )
- prompt = history + self.assistant_label
- input_ids = self.tokenizer.encode(prompt, return_tensors="pt").to(self.config.fastchat_t5.device)
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.fastchat_t5.max_new_tokens,
- temperature=self.config.fastchat_t5.temperature,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generation = self.tokenizer.decode( output[0], skip_special_tokens=True )
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- FastChatT5Miner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/README.md
deleted file mode 100644
index 733d99467..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/README.md
+++ /dev/null
@@ -1,139 +0,0 @@
-## Gpt4_x_vicuna Miner
-Gpt4_x_vicuna Language Model Serving with BitTensor
-This code is for running the Gpt4_x_vicuna by Nous Research model through the BitTensor framework.
-
-# Overview
-
-## Contents
-
-- [Licence](#Licence)
-- [Installing Dependencies](#installing-dependencies)
-- [Starting Miner](#starting-miner)
-
-
-# Licence
-gpl
-
-# Installing Dependencies
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/requirements.txt
-```
-
-# Starting Miner
-To start the miner, all you need to do is to specify the path to the model, or the name on Huggingface hub, and it will be downloaded.
-
-You can find different model checkpoints by searching Huggingface, or by looking at Nous Research's Huggingface page https://huggingface.co/NousResearch
-
-```
-python3 neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/neuron.py --gpt4_x_vicuna.model_name GPT4_X_VICUNA.MODEL_NAME_OR_PATH
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--gpt4_x_vicuna.model_name GPT4_X_VICUNA.MODEL_NAME] [--gpt4_x_vicuna.device GPT4_X_VICUNA.DEVICE] [--gpt4_x_vicuna.max_new_tokens GPT4_X_VICUNA.MAX_NEW_TOKENS]
- [--gpt4_x_vicuna.temperature GPT4_X_VICUNA.TEMPERATURE] [--gpt4_x_vicuna.do_sample] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --neoxt.model_name NEOXT.MODEL_NAME
- Name/path of model to load of model to load
- --gpt4_x_vicuna.device GPT4_X_VICUNA.DEVICE
- Device to load model
- --gpt4_x_vicuna.max_new_tokens GPT4_X_VICUNA.MAX_NEW_TOKENS
- Max tokens for model output.
- --gpt4_x_vicuna.temperature GPT4_X_VICUNA.TEMPERATURE
- Sampling temperature of model
- --gpt4_x_vicuna.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/neuron.py
deleted file mode 100644
index a3a49ff67..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/neuron.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-class Gpt4_x_vicunaMiner( bittensor.HuggingFaceMiner ):
- arg_prefix = 'gpt4_x_vicuna'
- system_label = '### System:'
- user_label = '### User:'
- assistant_label = '### Response:'
-
- def load_tokenizer(self):
- return AutoTokenizer.from_pretrained( self.config.gpt4_x_vicuna.model_name, use_fast=False )
-
- def load_model(self):
- return AutoModelForCausalLM.from_pretrained( self.config.gpt4_x_vicuna.model_name, torch_dtype = torch.float16, low_cpu_mem_usage=True )
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
-
- history = self.process_history( messages )
- prompt = history + self.assistant_label
-
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.gpt4_x_vicuna.device )
-
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.gpt4_x_vicuna.max_new_tokens,
- temperature=self.config.gpt4_x_vicuna.temperature,
- do_sample=self.config.gpt4_x_vicuna.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
-
- bittensor.logging.debug( "Messages: " + str( messages ) )
- bittensor.logging.debug( "Prompt: " + str( prompt ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- Gpt4_x_vicunaMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/requirements.txt
deleted file mode 100644
index 5e83b53a0..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/gpt4_x_vicuna/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-transformers>=4.28.0
-fschat
-tokenizers>=0.13.3
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/README.md
deleted file mode 100644
index 5ecdb2420..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/README.md
+++ /dev/null
@@ -1,150 +0,0 @@
-# Guanaco Miner
-timdettmers Guanaco Language Model Serving with BitTensor
-This code is for running a language model powered by togethercomputer through the BitTensor framework.
-Reference: [code](https://github.com/artidoro/qlora)
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/guanaco/requirements.txt
-python neurons/text/prompting/miners/huggingface/guanaco/neuron.py --guanaco.model_name timdettmers/guanaco-33b-merged --guanaco.device_map auto
-```
-
-# Full Usage
-```
-usage: guanaco_miner.py [-h] [--guanaco.model_name GUANACO.MODEL_NAME] [--guanaco.api_key GUANACO.API_KEY]
- [--guanaco.device GUANACO.DEVICE] [--guanaco.max_new_tokens GUANACO.MAX_NEW_TOKENS]
- [--guanaco.temperature GUANACO.TEMPERATURE] [--guanaco.do_sample]
- [--guanaco.repetition_penalty GUANACO.REPETITION_PENALTY] [--guanaco.do_prompt_injection]
- [--guanaco.system_prompt GUANACO.SYSTEM_PROMPT]
- [--guanaco.repetition-penalty GUANACO.REPETITION_PENALTY] [--guanaco.top_p GUANACO.TOP_P]
- [--guanaco.top_k GUANACO.TOP_K] [--guanaco.load_in_8bit GUANACO.LOAD_IN_8BIT]
- [--guanaco.device_map GUANACO.DEVICE_MAP]
- [--guanaco.pad_tokens GUANACO.PAD_TOKENS [GUANACO.PAD_TOKENS ...]] [--netuid NETUID]
- [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH]
- [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE]
- [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE]
- [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME]
- [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP]
- [--axon.max_workers AXON.MAX_WORKERS] [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS]
- [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT]
- [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL]
- [--subtensor.register.no_output_in_place] [--subtensor.register.verbose]
- [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace]
- [--logging.record_log] [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --guanaco.model_name GUANACO.MODEL_NAME
- Name or path of model to load
- --guanaco.api_key GUANACO.API_KEY
- huggingface api key
- --guanaco.device GUANACO.DEVICE
- Device to load model
- --guanaco.max_new_tokens GUANACO.MAX_NEW_TOKENS
- Max tokens for model output.
- --guanaco.temperature GUANACO.TEMPERATURE
- Sampling temperature of model
- --guanaco.do_sample Whether to use multinomial sampling.
- --guanaco.repetition_penalty GUANACO.REPETITION_PENALTY
- Repetition penalty for model
- --guanaco.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --guanaco.system_prompt GUANACO.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --guanaco.repetition-penalty GUANACO.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --guanaco.top_p GUANACO.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --guanaco.top_k GUANACO.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --guanaco.load_in_8bit GUANACO.LOAD_IN_8BIT
- Load model in 8 bit precision
- --guanaco.device_map GUANACO.DEVICE_MAP
- Device map for model parallelism.
- --guanaco.pad_tokens GUANACO.PAD_TOKENS [GUANACO.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this
- wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc
- server distributes new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running
- network) -- mock (creates a mock connection (for testing)) If this option is set it overloads
- subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/neuron.py
deleted file mode 100644
index 6327c3e5b..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/neuron.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-class GuanacoMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = 'guanaco'
- assistant_label: str = '### Assistant:'
- user_label: str = '### Human:'
- system_label: str = ''
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.guanaco.model_name )
-
- def load_model( self ):
- return AutoModelForCausalLM.from_pretrained(
- self.config.guanaco.model_name,
- torch_dtype = torch.float16,
- low_cpu_mem_usage=True,
- device_map=self.config.guanaco.device_map
- )
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
- history = self.process_history( messages )
- prompt = history + self.assistant_label
-
- generate_kwargs = dict(
- temperature=self.config.guanaco.temperature,
- max_new_tokens=self.config.guanaco.max_new_tokens,
- top_p=self.config.guanaco.top_p,
- repetition_penalty=self.config.guanaco.repetition_penalty,
- do_sample=self.config.guanaco.do_sample,
- )
- if '33B' in self.config.guanaco.model_name: # Tim Dettmers 33B model-specific parameters
- generate_kwargs['truncate'] = 999
- generate_kwargs['seed'] = 42
-
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.guanaco.device )
- output = self.model.generate(
- input_ids,
- **generate_kwargs
- )
- generated_text = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
- generation = generated_text.split( self.assistant_label )[0].strip()
-
- bittensor.logging.debug("Message: " + str( messages ) )
- bittensor.logging.debug("Generation: " + str( generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- GuanacoMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/requirements.txt
deleted file mode 100644
index 33059ec77..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/guanaco/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-transformers>=4.29.2
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/README.md
deleted file mode 100644
index 6e56fed45..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/README.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# Koala Miner
-Koala Language Model Serving with BitTensor
-This code is for running the Koala model through the BitTensor framework.
-
-# Overview
-
-## Contents
-
-- [Installing Dependencies](#installing-Dependencies)
-- [Converting Weights Into Model](#converting-weights-into-model)
-- [Starting Miner](#starting-miner)
-
-
-# Installing Dependencies
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/koala/requirements.txt
-```
-
-# Converting Weights Into Model
-If you already have a converted checkpoint of the model, you can skip this step.
-
-Original documentation for creating the model from weights can be found [here](https://github.com/young-geng/EasyLM/blob/main/docs/koala.md)
-
-## Obtaining the Wegith Diff of Koala
-Due to the licence of the LLaMA model, the fine-tuned
-Koala model weights can not be directly released. Instead, the diff of weights, which can be used
-to recover the Koala model weights with the original LLaMA model weights, is released. The diff
-weights can be downloaded from the following sources:
-* [HuggingFace Hub](https://huggingface.co/young-geng/koala/tree/main).
-* [Google Drive](https://drive.google.com/drive/folders/10f7wrlAFoPIy-TECHsx9DKIvbQYunCfl?usp=sharing).
-
-## Recovering the Koala Model Weights
-The first step of recovering the Koala model weights is to obtain the original
-LLaMA model weights and convert it to EasyLM checkpoint format. To convert the weights,
-use the following command:
-
-``` shell
-python -m EasyLM.models.llama.convert_torch_to_easylm \
- --checkpoint_dir='path/to/torch/llama/checkpoint/directory' \
- --output_file='path/to/output/easylm/checkpoint/file' \
- --streaming=True
-```
-
-This script will convert the official torch checkpoint from Meta to the
-streaming checkpoint format used by EasyLM. For more information
-about the checkpoint format of EasyLM, see [the checkpointing documentation](checkpointing.md).
-
-
-After converting the original LLaMA model weights, you can recover the Koala
-model weights with the following command:
-
-``` shell
-python -m EasyLM.scripts.diff_checkpoint \
- --recover_diff=True \
- --load_base_checkpoint='params::path/to/llama/checkpoint/file' \
- --load_target_checkpoint='params::path/to/koala/diff/checkpoint/file' \
- --output_file='path/to/output/checkpoint/file' \
- --streaming=True
-```
-
-
-# Starting Miner
-```
-python3 neurons/text/prompting/miners/huggingface/koala_miner.py --koala.model_name TheBloke/koala-7B-HF
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--koala.model_name KOALA.MODEL_NAME] [--koala.device KOALA.DEVICE] [--koala.max_new_tokens KOALA.MAX_NEW_TOKENS]
- [--koala.temperature KOALA.TEMPERATURE] [--koala.do_sample] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --neoxt.model_name NEOXT.MODEL_NAME
- Name/path of model to load of model to load
- --koala.device KOALA.DEVICE
- Device to load model
- --koala.max_new_tokens KOALA.MAX_NEW_TOKENS
- Max tokens for model output.
- --koala.temperature KOALA.TEMPERATURE
- Sampling temperature of model
- --koala.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/neuron.py
deleted file mode 100644
index 5f2bee3de..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/neuron.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-class KoalaMiner( bittensor.HuggingFaceMiner ):
- arg_prefix: str = 'koala'
- assistant_label: str = 'GPT:'
- user_label: str = 'USER:'
- system_label: str = ''
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.koala.model_name, use_fast=False )
-
- def load_model( self ):
- return AutoModelForCausalLM.from_pretrained( self.config.koala.model_name, torch_dtype = torch.float16, low_cpu_mem_usage=True )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self._process_history( messages )
- prompt = history + self.system_label
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.koala.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.koala.max_new_tokens,
- temperature=self.config.koala.temperature,
- do_sample=self.config.koala.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- KoalaMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/requirements.txt
deleted file mode 100644
index bd7d62c8c..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/koala/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-transformers>=4.28.0
-fschat
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/README.md
deleted file mode 100644
index c80893753..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/README.md
+++ /dev/null
@@ -1,139 +0,0 @@
-## MPT_Chat Miner
-MPT_Chat Language Model Serving with BitTensor
-This code is for running the Mpt_chat by MosaicML model through the BitTensor framework.
-
-# Overview
-
-## Contents
-
-- [Licence](#Licence)
-- [Installing Dependencies](#installing-dependencies)
-- [Starting Miner](#starting-miner)
-
-
-# Licence
-CC-By-NC-SA-4.0 (non-commercial use only)
-
-
-# Installing Dependencies
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/mpt_chat/requirements.txt
-```
-
-# Starting Miner
-To start the miner, all you need to do is to specify the path to the model, or the name on Huggingface hub, and it will be downloaded.
-
-You can find different model checkpoints by searching Huggingface, or by looking at MosaicML's Huggingface page https://huggingface.co/NousResearch
-```
-python3 neurons/text/prompting/miners/huggingface/mpt_chat/neuron.py --mpt_chat.model_name MPT_CHAT.MODEL_NAME_OR_PATH
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--mpt_chat.model_name MPT_CHAT.MODEL_NAME] [--mpt_chat.device MPT_CHAT.DEVICE] [--mpt_chat.max_new_tokens MPT_CHAT.MAX_NEW_TOKENS]
- [--mpt_chat.temperature MPT_CHAT.TEMPERATURE] [--mpt_chat.do_sample] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --neoxt.model_name NEOXT.MODEL_NAME
- Name/path of model to load of model to load
- --mpt_chat.device MPT_CHAT.DEVICE
- Device to load model
- --mpt_chat.max_new_tokens MPT_CHAT.MAX_NEW_TOKENS
- Max tokens for model output.
- --mpt_chat.temperature MPT_CHAT.TEMPERATURE
- Sampling temperature of model
- --mpt_chat.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/neuron.py
deleted file mode 100644
index a3ac45bc5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/neuron.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM, AutoConfig
-
-class Mpt_chatMiner( bittensor.HuggingFaceMiner ):
- arg_prefix: str = 'mpt_chat'
- system_label: str = '<|im_start|>system\n'
- user_label: str = '<|im_start|>user\n'
- assistant_label: str = '<|im_start|>assistant\n'
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument( '--mpt_chat.tokenizer_name', type=str, required=False, help='Name/path of model to load' , default="EleutherAI/gpt-neox-20b")
- parser.add_argument( '--mpt_chat.use_triton', action='store_true', default=False, help='Whether to use a triton to speed up inference' )
-
- def load_tokenizer(self):
- return AutoTokenizer.from_pretrained( self.config.mpt_chat.tokenizer_name )
-
- def load_model(self):
- config = AutoConfig.from_pretrained( 'mosaicml/mpt-7b-chat', trust_remote_code=True )
-
- if self.config.mpt_chat.use_triton:
- config.attn_config['attn_impl'] = 'triton'
-
- model = AutoModelForCausalLM.from_pretrained(
- self.config.mpt_chat.model_name,
- torch_dtype = torch.float16,
- low_cpu_mem_usage=True,
- trust_remote_code=True,
- config=config
- )
- return model
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
-
- history = self.process_history( messages )
- prompt = history + self.assistant_label
-
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.mpt_chat.device )
-
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.mpt_chat.max_new_tokens,
- temperature=self.config.mpt_chat.temperature,
- do_sample=self.config.mpt_chat.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
-
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=False ).strip()
- generation = generation.split( "<|endoftext|>" )[0]
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Prompt: " + str( prompt ) )
- bittensor.logging.debug( "Generation: " + str( generation.replace( "<", "-" ) ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- Mpt_chatMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/requirements.txt
deleted file mode 100644
index 406fd1d02..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/mpt_chat/requirements.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-transformers>=4.28.0
-fschat
-tokenizers>=0.13.3
-accelerate
-einops
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/README.md
deleted file mode 100644
index ffb387c9e..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/README.md
+++ /dev/null
@@ -1,136 +0,0 @@
-## Neoxt Miner
-togethercomputer/GPT-NeoXT-Chat-Base-20B Language Model Serving with BitTensor
-This code is for running a language model powered by togethercomputer through the BitTensor framework.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/neoxt/requirements.txt
-python3 neurons/text/prompting/miners/huggingface/neoxt/neuron.py --neoxt.model_name togethercomputer/GPT-NeoXT-Chat-Base-20B
-```
-
-# Full Usage
-```
-usage: neoxt_miner.py [-h] --neoxt.model_name NEOXT.MODEL_NAME [--neoxt.device NEOXT.DEVICE] [--neoxt.max_new_tokens NEOXT.MAX_NEW_TOKENS]
- [--neoxt.temperature NEOXT.TEMPERATURE] [--neoxt.do_sample] [--neoxt.repetition_penalty NEOXT.REPETITION_PENALTY]
- [--neoxt.do_prompt_injection] [--neoxt.system_prompt NEOXT.SYSTEM_PROMPT]
- [--neoxt.repetition-penalty NEOXT.REPETITION_PENALTY] [--neoxt.top_p NEOXT.TOP_P] [--neoxt.top_k NEOXT.TOP_K]
- [--neoxt.load_in_8bit NEOXT.LOAD_IN_8BIT] [--neoxt.pad_tokens NEOXT.PAD_TOKENS [NEOXT.PAD_TOKENS ...]] [--netuid NETUID]
- [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE]
- [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY]
- [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE]
- [--axon.port AXON.PORT] [--axon.ip AXON.IP] [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP]
- [--axon.max_workers AXON.MAX_WORKERS] [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS]
- [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --neoxt.model_name NEOXT.MODEL_NAME
- Name or path of model to load
- --neoxt.device NEOXT.DEVICE
- Device to load model
- --neoxt.max_new_tokens NEOXT.MAX_NEW_TOKENS
- Max tokens for model output.
- --neoxt.temperature NEOXT.TEMPERATURE
- Sampling temperature of model
- --neoxt.do_sample Whether to use multinomial sampling.
- --neoxt.repetition_penalty NEOXT.REPETITION_PENALTY
- Repetition penalty for model
- --neoxt.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --neoxt.system_prompt NEOXT.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --neoxt.repetition-penalty NEOXT.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --neoxt.top_p NEOXT.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --neoxt.top_k NEOXT.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --neoxt.load_in_8bit NEOXT.LOAD_IN_8BIT
- Load model in 8 bit precision
- --neoxt.pad_tokens NEOXT.PAD_TOKENS [NEOXT.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new
- worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock
- (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point
- node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/neuron.py
deleted file mode 100644
index 9fb87cc8d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/neuron.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-
-class NeoxtMiner( bittensor.HuggingFaceMiner ):
- arg_prefix: str = 'neoxt'
- assistant_label: str = ':'
- user_label: str = ':'
- system_label: str = ''
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.neoxt.model_name )
-
- def load_model( self ):
- return AutoModelForCausalLM.from_pretrained( self.config.neoxt.model_name, torch_dtype = torch.float16, low_cpu_mem_usage=True )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self.process_history( messages )
- prompt = history + self.assistant_label
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.neoxt.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.neoxt.max_new_tokens,
- temperature=self.config.neoxt.temperature,
- do_sample=self.config.neoxt.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generated_text = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
- generation = generated_text.split( "" )[0].strip()
-
- bittensor.logging.debug( "Message: " + str( messages ).replace( "<","-" ).replace( ">","-" ) )
- bittensor.logging.debug( "Generation: " + str( generation ).replace( "<","-" ).replace( ">","-" ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- NeoxtMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/requirements.txt
deleted file mode 100644
index b33885a65..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/neoxt/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-transformers>=4.27.4
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/oasst_pythia/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/oasst_pythia/README.md
deleted file mode 100644
index 6a011725d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/oasst_pythia/README.md
+++ /dev/null
@@ -1,118 +0,0 @@
-
-## OpenAssistant Pythia Miner
-OpenAssistant's Pythia (12B) completion miner for bittensor's prompting network.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/oasst_pythia/requirements.txt
-python3 neurons/text/prompting/miners/huggingface/oasst_pythia/neuron.py --oasst_pythia.OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--pythia12B.model_name PYTHIA12B.MODEL_NAME] [--pythia12B.load_in_8bit PYTHIA12B.LOAD_IN_8BIT] [--pythia12B.max_new_tokens PYTHIA12B.MAX_NEW_TOKENS]
- [--pythia12B.temperature PYTHIA12B.TEMPERATURE] [--pythia12B.greedy_sampling] [--pythia12B.repetition-penalty PYTHIA12B.REPETITION_PENALTY]
- [--pythia12B.top_p PYTHIA12B.TOP_P] [--pythia12B.top_k PYTHIA12B.TOP_K] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE]
- [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN] [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT]
- [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL]
- [--subtensor.register.no_output_in_place] [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]] [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB]
- [--logging.debug] [--logging.trace] [--logging.record_log] [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-optional arguments:
- -h, --help show this help message and exit
- --pythia12B.model_name PYTHIA12B.MODEL_NAME
- Name/path of model to load
- --pythia12B.load_in_8bit PYTHIA12B.LOAD_IN_8BIT
- Load model in 8 bit precision
- --pythia12B.max_new_tokens PYTHIA12B.MAX_NEW_TOKENS
- Max tokens for model output.
- --pythia12B.temperature PYTHIA12B.TEMPERATURE
- Sampling temperature of model
- --pythia12B.greedy_sampling
- Whether to use greedy sampling or not (if not, uses multinomial sampling).
- --pythia12B.repetition-penalty PYTHIA12B.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --pythia12B.top_p PYTHIA12B.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --pythia12B.top_k PYTHIA12B.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up
- to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for
- testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/oasst_pythia/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/oasst_pythia/neuron.py
deleted file mode 100644
index 9e718eebb..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/oasst_pythia/neuron.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, GPTNeoXForCausalLM
-from transformers import StoppingCriteria, StoppingCriteriaList
-
-class StopOnTokens( StoppingCriteria ):
- def __init__( self, stop_token_ids: List[int] = None ):
- self.stop_token_ids = stop_token_ids
-
- def __call__( self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs ) -> bool:
- for stop_id in self.stop_token_ids:
- if input_ids[0][-1] == stop_id:
- return True
- return False
-
-class OasstPythiaMiner( bittensor.HuggingFaceMiner ):
- arg_prefix = 'oasst_pythia'
- system_label = "<|system|>"
- assistant_label = "<|assistant|>"
- user_label = "<|prompter|>"
-
- def __init__( self ):
- super( OasstPythiaMiner, self ).__init__()
- self.stop = StopOnTokens( self.tokenizer.convert_tokens_to_ids( [ "<|endoftext|>" ] ) )
-
- def load_tokenizer(self):
- return AutoTokenizer.from_pretrained( self.config.oasst_pythia.model_name, torch_dtype=torch.bfloat16 )
-
- def load_model( self ):
- bittensor.logging.info( 'Loading ' + str( self.config.oasst_pythia.model_name ) )
- model = GPTNeoXForCausalLM.from_pretrained(
- self.config.oasst_pythia.model_name,
- device_map="auto",
- low_cpu_mem_usage=True,
- torch_dtype=torch.bfloat16
- )
- bittensor.logging.info( 'Model loaded!' )
- return model
-
- def forward( self, messages: List[Dict[str, str]] ):
- history = self.process_history(messages)
- prompt = history + self.assistant_label
-
- inputs = self.tokenizer( prompt, return_tensors="pt" )
- inputs = inputs.to( self.model.device )
-
- gkw = {
- **{
- "input_ids": inputs.input_ids,
- "attention_mask": inputs.attention_mask,
- "max_new_tokens": self.config.oasst_pythia.max_new_tokens,
- "temperature": self.config.oasst_pythia.temperature,
- "do_sample": self.config.oasst_pythia.do_sample,
- "top_p": self.config.oasst_pythia.top_p,
- "top_k": self.config.oasst_pythia.top_k,
- "repetition_penalty": self.config.oasst_pythia.repetition_penalty,
- "stopping_criteria": StoppingCriteriaList( [ self.stop ] ),
- "pad_token_id": self.tokenizer.eos_token_id,
- },
- }
- output = self.model.generate( **gkw )
- generation = self.tokenizer.decode( output[0][inputs.input_ids.shape[1]:], skip_special_tokens=True )
-
- bittensor.logging.debug( "Message: " + str(messages ) )
- bittensor.logging.debug( "Generation: " + str(generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- OasstPythiaMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/README.md
deleted file mode 100644
index e81e38d30..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/README.md
+++ /dev/null
@@ -1,139 +0,0 @@
-## OpenLLaMA Miner
-OpenLLaMA Language Model Serving with BitTensor
-This code is for running the Open_llama model by OpenLM-Research through the BitTensor framework.
-
-# Overview
-
-## Contents
-
-- [Licence](#licence)
-- [Model Download](#model-download)
-- [Installing Dependencies](#installing-dependencies)
-- [Starting Miner](#starting-miner)
-
-# Licence
-Apache 2.0 (Open source and commercial purposes allowed)
-
-# Installing Dependencies
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/open_llama/requirements.txt
-```
-
-# Starting Miner
-To start the miner, all you need to do is to specify the path to the model, or the name on Huggingface hub, and it will be downloaded.
-
-You can find different model checkpoints by searching Huggingface, or by looking at OpenLM-Research's Huggingface page https://huggingface.co/openlm-research
-
-```
-python3 neurons/text/prompting/miners/huggingface/open_llama/neuron.py --open_llama.model_name OPEN_LLAMA.MODEL_NAME_OR_PATH
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--open_llama.model_name OPEN_LLAMA.MODEL_NAME] [--open_llama.device OPEN_LLAMA.DEVICE] [--open_llama.max_new_tokens OPEN_LLAMA.MAX_NEW_TOKENS]
- [--open_llama.temperature OPEN_LLAMA.TEMPERATURE] [--open_llama.do_sample] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --neoxt.model_name NEOXT.MODEL_NAME
- Name/path of model to load of model to load
- --open_llama.device OPEN_LLAMA.DEVICE
- Device to load model
- --open_llama.max_new_tokens OPEN_LLAMA.MAX_NEW_TOKENS
- Max tokens for model output.
- --open_llama.temperature OPEN_LLAMA.TEMPERATURE
- Sampling temperature of model
- --open_llama.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/neuron.py
deleted file mode 100644
index e004009ff..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/neuron.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import LlamaForCausalLM, LlamaTokenizer
-
-class OpenLlamaMiner( bittensor.HuggingFaceMiner ):
- arg_prefix = 'open_llama'
- system_label = '\nSystem:'
- assistant_label = '\nAssistant:'
- user_label = '\nUser:'
-
- def load_tokenizer( self ):
- return LlamaTokenizer.from_pretrained( self.config.open_llama.model_name, use_fast=False )
-
- def load_model( self ):
- return LlamaForCausalLM.from_pretrained( self.config.open_llama.model_name, torch_dtype = torch.float16, low_cpu_mem_usage=True )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
-
- history = self.process_history( messages )
- prompt = history + self.assistant_label
-
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.open_llama.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.open_llama.max_new_tokens,
- temperature=self.config.open_llama.temperature,
- do_sample=self.config.open_llama.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
-
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
- generation = generation.split( "User:" )[0].strip()
-
- # Logging input and generation if debugging is active
- bittensor.logging.debug( "Prompt: " + str( prompt) )
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ).replace( "<", "-" ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- OpenLlamaMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/requirements.txt
deleted file mode 100644
index 98637aee3..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/open_llama/requirements.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-git+https://github.com/huggingface/transformers
-sentencepiece
-fschat
-tokenizers>=0.13.3
-accelerate
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/README.md
deleted file mode 100644
index b5f5af5da..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/README.md
+++ /dev/null
@@ -1,136 +0,0 @@
-# Pythia Miner
-togethercomputer/Pythia-7B Language Model Serving with BitTensor
-This code is for running a language model powered by togethercomputer through the BitTensor framework.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/pythia/requirements.txt
-python3 neurons/text/prompting/miners/huggingface/pythia/neuron.py --pythia.model_name togethercomputer/Pythia-Chat-Base-7B
-```
-
-# Full Usage
-```
-usage: pythia_miner.py [-h] --pythia.model_name PYTHIA.MODEL_NAME [--pythia.device PYTHIA.DEVICE] [--pythia.max_new_tokens PYTHIA.MAX_NEW_TOKENS]
- [--pythia.temperature PYTHIA.TEMPERATURE] [--pythia.do_sample] [--pythia.repetition_penalty PYTHIA.REPETITION_PENALTY]
- [--pythia.do_prompt_injection] [--pythia.system_prompt PYTHIA.SYSTEM_PROMPT]
- [--pythia.repetition-penalty PYTHIA.REPETITION_PENALTY] [--pythia.top_p PYTHIA.TOP_P] [--pythia.top_k PYTHIA.TOP_K]
- [--pythia.load_in_8bit PYTHIA.LOAD_IN_8BIT] [--pythia.pad_tokens PYTHIA.PAD_TOKENS [PYTHIA.PAD_TOKENS ...]]
- [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE]
- [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY]
- [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE]
- [--axon.port AXON.PORT] [--axon.ip AXON.IP] [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP]
- [--axon.max_workers AXON.MAX_WORKERS] [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS]
- [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --pythia.model_name PYTHIA.MODEL_NAME
- Name or path of model to load
- --pythia.device PYTHIA.DEVICE
- Device to load model
- --pythia.max_new_tokens PYTHIA.MAX_NEW_TOKENS
- Max tokens for model output.
- --pythia.temperature PYTHIA.TEMPERATURE
- Sampling temperature of model
- --pythia.do_sample Whether to use multinomial sampling.
- --pythia.repetition_penalty PYTHIA.REPETITION_PENALTY
- Repetition penalty for model
- --pythia.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --pythia.system_prompt PYTHIA.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --pythia.repetition-penalty PYTHIA.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --pythia.top_p PYTHIA.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --pythia.top_k PYTHIA.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --pythia.load_in_8bit PYTHIA.LOAD_IN_8BIT
- Load model in 8 bit precision
- --pythia.pad_tokens PYTHIA.PAD_TOKENS [PYTHIA.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new
- worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock
- (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point
- node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/neuron.py
deleted file mode 100644
index 65d5620ff..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/neuron.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-class PythiaMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = 'pythia'
- assistant_label: str = ':'
- user_label: str = ':'
- system_label: str = ''
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.pythia.model_name )
-
- def load_model( self ):
- return AutoModelForCausalLM.from_pretrained( self.config.pythia.model_name, torch_dtype = torch.float16, low_cpu_mem_usage=True )
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
- history = self.process_history( messages )
- prompt = history + self.assistant_label
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.pythia.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.pythia.max_new_tokens,
- temperature=self.config.pythia.temperature,
- do_sample=self.config.pythia.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generated_text = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
- generation = generated_text.split( "" )[0].strip()
-
- bittensor.logging.debug("Message: " + str( messages ).replace( "<","-" ).replace( ">","-" ) )
- bittensor.logging.debug("Generation: " + str( generation ).replace( "<","-" ).replace( ">","-" ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- PythiaMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/requirements.txt
deleted file mode 100644
index b33885a65..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/pythia/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-transformers>=4.27.4
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/README.md
deleted file mode 100644
index d931a450c..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/README.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# Raven RWKV Miner
-BlinkDL/Raven-RWKV-7B Language Model Serving with BitTensor
-This code is for running a language model powered by BlinkDL through the BitTensor framework.
-
-## Setup
-Go to the huggingface repo for more information: [rwkv-4-raven](https://huggingface.co/BlinkDL/rwkv-4-raven)
-
-NOTE: You need to pass the path to the tokenizer.json from the command line.
-- Find it [here](https://huggingface.co/spaces/BlinkDL/Raven-RWKV-7B/resolve/main/20B_tokenizer.json)
-
-NOTE: You will want to browse and see what Raven model you wish to load [here](https://huggingface.co/BlinkDL/rwkv-4-raven/tree/main)
-e.g. `RWKV-4-Raven-7B-v11-Eng99%25-Other1%25-20230427-ctx8192` for Engligh 99% and Other languages 1%=
-e.g. `RWKV-4-Raven-7B-v11-Eng49%-Chn49%-Jpn1%-Other1%-20230430-ctx8192` for 49% English, 49% Chinese, 1% Japanese
-
-These percentages refer to the amount of training data from that particular language.
-
-# Usage
-```
-wget https://huggingface.co/spaces/BlinkDL/Raven-RWKV-7B/resolve/main/20B_tokenizer.json
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/raven-rwkv/requirements.txt
-python3 neurons/text/prompting/miners/huggingface/raven-rwkv/neuron.py --raven.tokenizer_path /home/jason/bittensor/20B_tokenizer.json \
- --raven.model_name RWKV-4-Raven-7B-v11x-Eng99%-Other1%-20230429-ctx8192 \
- --raven.repetition-penalty 0.2 --raven.top_p 0.0 --raven.temperature 1.0
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--raven.model_name RAVEN.MODEL_NAME] [--raven.repo_id RAVEN.REPO_ID] [--raven.tokenizer_path RAVEN.TOKENIZER_PATH] [--raven.device RAVEN.DEVICE] [--raven.ctx_limit RAVEN.CTX_LIMIT] [--raven.max_new_tokens RAVEN.MAX_NEW_TOKENS]
- [--raven.temperature RAVEN.TEMPERATURE] [--raven.top_p RAVEN.TOP_P] [--raven.do_prompt_injection] [--raven.system_prompt RAVEN.SYSTEM_PROMPT] [--raven.jit_on] [--raven.cuda_on] [--raven.strategy RAVEN.STRATEGY]
- [--raven.pad_tokens RAVEN.PAD_TOKENS [RAVEN.PAD_TOKENS ...]] [--raven.repetition_penalty RAVEN.REPETITION_PENALTY] [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN] [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.blacklist.vpermit_required] [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP] [--axon.external_port AXON.EXTERNAL_PORT]
- [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS] [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place] [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda]
- [--subtensor.register.cuda.no_cuda] [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]] [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --raven.model_name RAVEN.MODEL_NAME
- Name/path of model to load
- --raven.repo_id RAVEN.REPO_ID
- Repo id of model to load
- --raven.tokenizer_path RAVEN.TOKENIZER_PATH
- Path to tokenizer json file
- --raven.device RAVEN.DEVICE
- Device to load model
- --raven.ctx_limit RAVEN.CTX_LIMIT
- Max context length for model input.
- --raven.max_new_tokens RAVEN.MAX_NEW_TOKENS
- Max tokens for model output.
- --raven.temperature RAVEN.TEMPERATURE
- Sampling temperature of model
- --raven.top_p RAVEN.TOP_P
- Top p sampling of model
- --raven.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --raven.system_prompt RAVEN.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --raven.jit_on Whether to use Just-In-Time complication (JIT)
- --raven.cuda_on Whether to use CUDA kernel for seq mode (much faster). [Requires CUDA_HOME env_variable to be set]
- --raven.strategy RAVEN.STRATEGY
- Strategy to use for RWKV model
- --raven.pad_tokens RAVEN.PAD_TOKENS [RAVEN.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --raven.repetition_penalty RAVEN.REPETITION_PENALTY
- Repetition penalty for RWKV model
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, this miner will allow non-registered hotkeys to query it.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.blacklist.vpermit_required
- Require vpermit to query this miner.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that
- network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
- ```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/neuron.py
deleted file mode 100644
index a050ab8fa..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/neuron.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import os
-import argparse
-import bittensor
-from typing import List, Dict
-from huggingface_hub import hf_hub_download
-from rwkv.model import RWKV
-from rwkv.utils import PIPELINE
-
-class RavenMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix = 'raven'
- system_label = ""
- assistant_label = "Alice:"
- user_label = "Bob:"
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- super( RavenMiner, cls ).add_args( parser )
- parser.add_argument( '--raven.repo_id', type=str, default="BlinkDL/rwkv-4-raven", help='Repo id of model to load' )
- parser.add_argument( '--raven.tokenizer_path', type=str, required=True, help='Path to tokenizer json file' )
- parser.add_argument( '--raven.ctx_limit', type=int, help='Max context length for model input.', default=1536 )
- parser.add_argument( '--raven.jit_on', action='store_true', default=False, help='Whether to use Just-In-Time complication (JIT)' )
- parser.add_argument( '--raven.cuda_on', action='store_true', default=False, help='Whether to use CUDA kernel for seq mode (much faster). [Requires CUDA_HOME env_variable to be set]' )
- parser.add_argument( '--raven.strategy', type=str, default='cuda fp16i8 *8 -> cuda fp16', help='Strategy to use for RWKV model')
-
- def __init__(self):
- super( RavenMiner, self ).__init__()
-
- def load_model( self ):
- model_path = hf_hub_download( repo_id=self.config.raven.repo_id, filename=f"{self.config.raven.model_name}.pth" )
- model = RWKV( model=model_path, strategy=self.config.raven.strategy )
- return PIPELINE( model, self.config.raven.tokenizer_path )
-
- def load_tokenizer( self ):
- pass
-
- os.environ["RWKV_JIT_ON"] = '1' if self.config.raven.jit_on else '0'
- os.environ["RWKV_CUDA_ON"] = '1' if self.config.raven.cuda_on else '0'
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self.process_history( messages )
-
- out_tokens = []
- out_last = 0
- generation = ''
- occurrence = {}
- state = None
- for i in range( self.config.raven.max_new_tokens ):
- tokens = self.config.raven.pad_tokens + self.model.encode( history ) if i == 0 else [token]
-
- out, state = self.model.model.forward(tokens, state)
- for n in occurrence:
- out[n] -= ( self.config.raven.repetition_penalty + occurrence[n] * self.config.raven.repetition_penalty )
-
- token = self.model.sample_logits( out, temperature=self.config.raven.temperature, top_p=self.config.raven.top_p )
- if token == 0: break # exit when 'endoftext'
-
- out_tokens += [token]
- occurrence[token] = 1 + ( occurrence[token] if token in occurrence else 0 )
-
- tmp = self.model.decode( out_tokens[out_last:] )
- if ( '\ufffd' not in tmp ) and ( not tmp.endswith('\n') ):
- generation += tmp
- out_last = i + 1
-
- if '\n\n' in tmp: # exit when '\n\n'
- generation += tmp
- generation = generation.strip()
- break
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- RavenMiner().run()
-
-def test_miner( model ):
- prompt = """
- You are George Carlin.
- George Carlin is a comedian known for his witty, cutting, poignant observational comedy.
- He is also known for his social commentary, philosophy, and cutting remarks on religion.
- Write a joke about the following topic:
- """
-
- message = "who am I, really?"
-
- if prompt is not None:
- roles = ['system', 'user']
- messages = [ prompt, message ]
- else:
- roles = ['user']
- messages = [ message ]
-
- messages = [{'role': role, 'content': message} for role, message in zip(roles, messages)]
-
- return model.forward( messages )
-
-miner = RavenMiner()
-print( test_miner(miner) )
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/requirements.txt
deleted file mode 100644
index 2573350bc..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/raven/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rwkv
-huggingface_hub
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/README.md
deleted file mode 100644
index 965e435fc..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/README.md
+++ /dev/null
@@ -1,140 +0,0 @@
-
-## RoberMyers Miner
-Robert myers completion miner for bittensor's prompting network.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/robertmyers/requirements.txt
-python3 neurons/text/prompting/miners/huggingface/robertmyers/neuron.py --robertmyers.model_name robertmyers/bpt-sft
-```
-
-# Full Usage
-```
-usage: robertmyers_miner.py [-h] --robertmyers.model_name ROBERTMYERS.MODEL_NAME [--robertmyers.device ROBERTMYERS.DEVICE]
- [--robertmyers.max_new_tokens ROBERTMYERS.MAX_NEW_TOKENS] [--robertmyers.temperature ROBERTMYERS.TEMPERATURE]
- [--robertmyers.do_sample] [--robertmyers.repetition_penalty ROBERTMYERS.REPETITION_PENALTY]
- [--robertmyers.do_prompt_injection] [--robertmyers.system_prompt ROBERTMYERS.SYSTEM_PROMPT]
- [--robertmyers.repetition-penalty ROBERTMYERS.REPETITION_PENALTY] [--robertmyers.top_p ROBERTMYERS.TOP_P]
- [--robertmyers.top_k ROBERTMYERS.TOP_K] [--robertmyers.load_in_8bit ROBERTMYERS.LOAD_IN_8BIT]
- [--robertmyers.pad_tokens ROBERTMYERS.PAD_TOKENS [ROBERTMYERS.PAD_TOKENS ...]] [--netuid NETUID]
- [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE]
- [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY]
- [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE]
- [--axon.port AXON.PORT] [--axon.ip AXON.IP] [--axon.external_port AXON.EXTERNAL_PORT]
- [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --robertmyers.model_name ROBERTMYERS.MODEL_NAME
- Name or path of model to load
- --robertmyers.device ROBERTMYERS.DEVICE
- Device to load model
- --robertmyers.max_new_tokens ROBERTMYERS.MAX_NEW_TOKENS
- Max tokens for model output.
- --robertmyers.temperature ROBERTMYERS.TEMPERATURE
- Sampling temperature of model
- --robertmyers.do_sample
- Whether to use multinomial sampling.
- --robertmyers.repetition_penalty ROBERTMYERS.REPETITION_PENALTY
- Repetition penalty for model
- --robertmyers.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --robertmyers.system_prompt ROBERTMYERS.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --robertmyers.repetition-penalty ROBERTMYERS.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --robertmyers.top_p ROBERTMYERS.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --robertmyers.top_k ROBERTMYERS.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --robertmyers.load_in_8bit ROBERTMYERS.LOAD_IN_8BIT
- Load model in 8 bit precision
- --robertmyers.pad_tokens ROBERTMYERS.PAD_TOKENS [ROBERTMYERS.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new
- worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock
- (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point
- node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/neuron.py
deleted file mode 100644
index 2cbd84c6d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/neuron.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-# General.
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
-
-class RobertMyersMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = 'robertmyers'
- system_label: str = 'system:'
- assistant_label: str = 'assistant:'
- user_label: str = 'user:'
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.robertmyers.model_name )
-
- def load_model( self ):
- model = AutoModelForCausalLM.from_pretrained( self.config.robertmyers.model_name, torch_dtype=torch.float16 )
- model.to( self.config.robertmyers.device )
- return pipeline(
- "text-generation", model, tokenizer=self.tokenizer,
- device = 0, max_new_tokens = self.config.robertmyers.max_new_tokens,
- temperature = self.config.robertmyers.temperature,
- do_sample = self.config.robertmyers.do_sample, pad_token_id = self.tokenizer.eos_token_id
- )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self.process_history( messages )
- resp = self.model( history )[0]['generated_text'].split(':')[-1].replace( str( history ), "")
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- RobertMyersMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/requirements.txt
deleted file mode 100644
index bab195ea3..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/robertmyers/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-xformers
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/README.md
deleted file mode 100644
index f77f61569..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/README.md
+++ /dev/null
@@ -1,158 +0,0 @@
-## StabilityAI Miner
-StabilityAI 7B completion miner for bittensor's prompting network.
-
-# Example Usage
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/stabilityai/requirements.txt
-python3 neurons/text/prompting/miners/huggingface/stabilityai/neuron.py --stabilityai.model_size 7 # for 7B model
-
-# Some suggested settings
-python3 neurons/text/prompting/miners/huggingface/stabilityai/neuron.py --stabilityai.temperature 1.0 --stabilityai.top_k 10 --stabilityai.top_p 0.95 --stabilityai.do_sample
-```
-
-# Full Usage
-```
-usage: stabilityai_miner.py [-h] [--stabilityai.model_name STABILITYAI.MODEL_NAME] [--stabilityai.api_key STABILITYAI.API_KEY]
- [--stabilityai.device STABILITYAI.DEVICE] [--stabilityai.max_new_tokens STABILITYAI.MAX_NEW_TOKENS]
- [--stabilityai.temperature STABILITYAI.TEMPERATURE] [--stabilityai.do_sample]
- [--stabilityai.repetition_penalty STABILITYAI.REPETITION_PENALTY] [--stabilityai.do_prompt_injection]
- [--stabilityai.system_prompt STABILITYAI.SYSTEM_PROMPT]
- [--stabilityai.repetition-penalty STABILITYAI.REPETITION_PENALTY] [--stabilityai.top_p STABILITYAI.TOP_P]
- [--stabilityai.top_k STABILITYAI.TOP_K] [--stabilityai.load_in_8bit STABILITYAI.LOAD_IN_8BIT]
- [--stabilityai.pad_tokens STABILITYAI.PAD_TOKENS [STABILITYAI.PAD_TOKENS ...]] [--stabilityai.model_size {3,7}]
- [--stabilityai.suffix STABILITYAI.SUFFIX] [--stabilityai.num_return_sequences STABILITYAI.NUM_RETURN_SEQUENCES]
- [--stabilityai.num_beams STABILITYAI.NUM_BEAMS] [--stabilityai.stopping_criteria STABILITYAI.STOPPING_CRITERIA]
- [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH]
- [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE]
- [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE]
- [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY]
- [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE]
- [--axon.port AXON.PORT] [--axon.ip AXON.IP] [--axon.external_port AXON.EXTERNAL_PORT]
- [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --stabilityai.model_name STABILITYAI.MODEL_NAME
- Name or path of model to load
- --stabilityai.api_key STABILITYAI.API_KEY
- huggingface api key
- --stabilityai.device STABILITYAI.DEVICE
- Device to load model
- --stabilityai.max_new_tokens STABILITYAI.MAX_NEW_TOKENS
- Max tokens for model output.
- --stabilityai.temperature STABILITYAI.TEMPERATURE
- Sampling temperature of model
- --stabilityai.do_sample
- Whether to use multinomial sampling.
- --stabilityai.repetition_penalty STABILITYAI.REPETITION_PENALTY
- Repetition penalty for model
- --stabilityai.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --stabilityai.system_prompt STABILITYAI.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --stabilityai.repetition-penalty STABILITYAI.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --stabilityai.top_p STABILITYAI.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --stabilityai.top_k STABILITYAI.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --stabilityai.load_in_8bit STABILITYAI.LOAD_IN_8BIT
- Load model in 8 bit precision
- --stabilityai.pad_tokens STABILITYAI.PAD_TOKENS [STABILITYAI.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --stabilityai.model_size {3,7}
- Run the 3B or 7B model.
- --stabilityai.suffix STABILITYAI.SUFFIX
- The suffix that comes after a completion of inserted text.
- --stabilityai.num_return_sequences STABILITYAI.NUM_RETURN_SEQUENCES
- Description of num_return_sequences
- --stabilityai.num_beams STABILITYAI.NUM_BEAMS
- Description of num_beams
- --stabilityai.stopping_criteria STABILITYAI.STOPPING_CRITERIA
- Description of stopping_criteria
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new
- worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock
- (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point
- node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/neuron.py
deleted file mode 100644
index 5a7ec17ca..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/neuron.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-
-# General.
-import torch
-import argparse
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, StoppingCriteria, StoppingCriteriaList
-
-class StopOnTokens( StoppingCriteria ):
- def __call__( self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs ) -> bool:
- stop_ids = [50278, 50279, 50277, 1, 0]
- for stop_id in stop_ids:
- if input_ids[0][-1] == stop_id:
- return True
- return False
-
-class StabilityAIMiner( bittensor.HuggingFaceMiner ):
- arg_prefix: str = 'stabilityai'
- system_label: str = '<|SYSTEM|>:'
- assistant_label: str = '<|ASSISTANT|>:'
- user_label: str = '<|USER|>:'
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- super( StabilityAIMiner, cls ).add_args( parser )
- parser.add_argument( '--stabilityai.model_size', type=int, choices=[3, 7], default=7, help='Run the 3B or 7B model.' )
- parser.add_argument( '--stabilityai.suffix', type=str, default=None, help="The suffix that comes after a completion of inserted text." )
- parser.add_argument( '--stabilityai.num_return_sequences', type=int, default=1, help='Description of num_return_sequences' )
- parser.add_argument( '--stabilityai.num_beams', type=int, default=1, help='Description of num_beams' )
- parser.add_argument( '--stabilityai.stopping_criteria', type=str, default='stop', help='Description of stopping_criteria' )
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained(
- "stabilityai/stablelm-tuned-alpha-{}b".format( self.config.stabilityai.model_size ),
- use_auth_token=self.config.stabilityai.api_key
- )
-
- def load_model( self ):
- model = AutoModelForCausalLM.from_pretrained(
- "stabilityai/stablelm-tuned-alpha-{}b".format( self.config.stabilityai.model_size ),
- use_auth_token=self.config.stabilityai.api_key,
- torch_dtype=torch.float16
- ).cuda()
-
- return pipeline(
- "text-generation",
- model,
- tokenizer = self.tokenizer,
- device = 0,
- max_new_tokens = self.config.stabilityai.max_new_tokens,
- num_return_sequences = self.config.stabilityai.num_return_sequences,
- num_beams = self.config.stabilityai.num_beams,
- do_sample = self.config.stabilityai.do_sample,
- temperature = self.config.stabilityai.temperature,
- top_p = self.config.stabilityai.top_p,
- top_k = self.config.stabilityai.top_k,
- stopping_criteria=StoppingCriteriaList( [StopOnTokens()] )
- )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self.process_history( messages )
- return self.model( history )[0]['generated_text'].split(':')[-1].replace( str( history ), "")
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- StabilityAIMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/stabilityai_requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/stabilityai_requirements.txt
deleted file mode 100644
index 747b7aa97..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/stabilityai/stabilityai_requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-transformers
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/README.md
deleted file mode 100644
index e7d2f55f8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/README.md
+++ /dev/null
@@ -1,183 +0,0 @@
-## Vicuna Miner
-Vicuna Language Model Serving with BitTensor
-This code is for running the Vicuna model through the BitTensor framework.
-
-# Overview
-
-## Contents
-
-- [Installing Dependencies](#installing-dependencies)
-- [Converting Weights Into Model](#converting-weights-into-model)
-- [Starting Miner](#starting-miner)
-
-
-# Installing Dependencies
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/huggingface/vicuna/requirements.txt
-```
-
-# Converting Weights Into Model
-If you already have a converted checkpoint of the model, you can skip this step.
-
-## Vicuna Weights
-The [Vicuna](https://vicuna.lmsys.org/) weights as delta weights to comply with the LLaMA model license.
-You can add our delta to the original LLaMA weights to obtain the Vicuna weights. Instructions:
-
-1. Get the original LLaMA weights in the huggingface format by following the instructions [here](https://huggingface.co/docs/transformers/main/model_doc/llama).
-2. Use the following scripts to get Vicuna weights by applying our delta. They will automatically download delta weights from our Hugging Face [account](https://huggingface.co/lmsys).
-
-**NOTE**:
-Weights v1.1 are only compatible with the latest main branch of huggingface/transformers and ``fschat >= 0.2.0``.
-Please update your local packages accordingly. If you follow the above commands to do a fresh install, then you should get all the correct versions.
-
-Depending on which conversion script was used to create the Huggingface checkpoint of Llama, you might get an error that the tokenizer can not be found when loading the tokenizer. You can then replace all AutoTokenizers command with the correct tokenizer (in the example "LlamaTokenizer"), using this command:
-```
-find /path/to/fastchat -type f -name '*.py' -exec sed -i 's/AutoTokenizer/LlamaTokenizer/g' {} +
-```
-
-### Vicuna-7B
-This conversion command needs around 30 GB of CPU RAM.
-If you do not have enough memory, you can create a large swap file that allows the operating system to automatically utilize the disk as virtual memory.
-```bash
-python3 -m fastchat.model.apply_delta \
- --base /path/to/llama-7b \
- --target /output/path/to/vicuna-7b \
- --delta lmsys/vicuna-7b-delta-v1.1
-```
-
-### Vicuna-13B
-This conversion command needs around 60 GB of CPU RAM.
-If you do not have enough memory, you can create a large swap file that allows the operating system to automatically utilize the disk as virtual memory.
-```bash
-python3 -m fastchat.model.apply_delta \
- --base /path/to/llama-13b \
- --target /output/path/to/vicuna-13b \
- --delta lmsys/vicuna-13b-delta-v1.1
-```
-
-
-# Starting Miner
-```
-# If using HuggingFace model directly, only need to supply the repo ID.
-python3 neurons/text/prompting/miners/huggingface/vicuna/neuron.py --vicuna.model_name
-
-# If merging the weights yourself supply the path.
-python3 neurons/text/prompting/miners/huggingface/vicuna/neuron.py --vicuna.model_name /path/to/merged/vicuna/weights
-
-```
-
-# Full Usage
-```
-usage: vicuna_miner.py [-h] --vicuna.model_name VICUNA.MODEL_NAME [--vicuna.device VICUNA.DEVICE] [--vicuna.max_new_tokens VICUNA.MAX_NEW_TOKENS] [--vicuna.temperature VICUNA.TEMPERATURE] [--vicuna.do_sample]
- [--vicuna.repetition_penalty VICUNA.REPETITION_PENALTY] [--vicuna.do_prompt_injection] [--vicuna.system_prompt VICUNA.SYSTEM_PROMPT] [--vicuna.repetition-penalty VICUNA.REPETITION_PENALTY] [--vicuna.top_p VICUNA.TOP_P]
- [--vicuna.top_k VICUNA.TOP_K] [--vicuna.load_in_8bit VICUNA.LOAD_IN_8BIT] [--vicuna.pad_tokens VICUNA.PAD_TOKENS [VICUNA.PAD_TOKENS ...]] [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH]
- [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN] [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]]
- [--neuron.blacklist.allow_non_registered] [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY]
- [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS] [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL]
- [--subtensor.register.no_output_in_place] [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]] [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --vicuna.model_name VICUNA.MODEL_NAME
- Name or path of model to load
- --vicuna.device VICUNA.DEVICE
- Device to load model
- --vicuna.max_new_tokens VICUNA.MAX_NEW_TOKENS
- Max tokens for model output.
- --vicuna.temperature VICUNA.TEMPERATURE
- Sampling temperature of model
- --vicuna.do_sample Whether to use multinomial sampling.
- --vicuna.repetition_penalty VICUNA.REPETITION_PENALTY
- Repetition penalty for model
- --vicuna.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --vicuna.system_prompt VICUNA.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --vicuna.repetition-penalty VICUNA.REPETITION_PENALTY
- Repetition penalty for greedy decoding. Between 1.0 and infinity. 1.0 means no penalty. Default: 1.0
- --vicuna.top_p VICUNA.TOP_P
- Top-p (nucleus) sampling. Defaults to 1.0 (top-k sampling). Must be between 0.0 and 1.0.
- --vicuna.top_k VICUNA.TOP_K
- Top-k sampling. Defaults to 0 (no top-k sampling). Must be between 0 and 1000.
- --vicuna.load_in_8bit VICUNA.LOAD_IN_8BIT
- Load model in 8 bit precision
- --vicuna.pad_tokens VICUNA.PAD_TOKENS [VICUNA.PAD_TOKENS ...]
- A list of integers separated by spaces for the pad_tokens.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an entry
- point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/neuron.py
deleted file mode 100644
index 61e466d11..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/neuron.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-class VicunaMiner( bittensor.HuggingFaceMiner ):
-
- arg_prefix: str = 'vicuna'
- system_label: str = ''
- assistant_label: str = 'ASSISTANT:'
- user_label: str = 'USER:'
-
- def __init__( self ):
- super( VicunaMiner, self ).__init__()
- print ( self.config )
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.vicuna.model_name, use_fast=False )
-
- def load_model( self ):
- return AutoModelForCausalLM.from_pretrained( self.config.vicuna.model_name, torch_dtype = torch.float16, low_cpu_mem_usage=True )
-
- def forward(self, messages: List[Dict[str, str]]) -> str:
-
- history = self.process_history( messages )
- prompt = history + self.assistant_label
- print(prompt)
-
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.vicuna.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.vicuna.max_new_tokens,
- temperature=self.config.vicuna.temperature,
- do_sample=self.config.vicuna.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
-
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
- print(generation)
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation ) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- VicunaMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/requirements.txt
deleted file mode 100644
index 5e83b53a0..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/vicuna/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-transformers>=4.28.0
-fschat
-tokenizers>=0.13.3
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/README.md
deleted file mode 100644
index 699dcd2b2..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/README.md
+++ /dev/null
@@ -1,117 +0,0 @@
-
-## WizardLM + Vicuna Miner
-WizardLM Vicuna completion miner for bittensor's prompting network.
-
-# Example Usage
-```
-python3 neurons/text/prompting/miners/huggingface/wizard_vicuna/neuron.py --wiz_vic.model_name
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--wiz_vic.model_name WIZ_VIC.MODEL_NAME] [--wiz_vic.device WIZ_VIC.DEVICE] [--wiz_vic.max_new_tokens WIZ_VIC.MAX_NEW_TOKENS]
- [--wiz_vic.temperature WIZ_VIC.TEMPERATURE] [--wiz_vic.greedy_decoding] [--wiz_vic.do_sample] [--wiz_vic.do_prompt_injection]
- [--wiz_vic.system_prompt WIZ_VIC.SYSTEM_PROMPT] [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH]
- [--neuron.no_set_weights] [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY] [--wallet.name WALLET.NAME]
- [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER]
- [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS] [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT]
- [--subtensor._mock] [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL]
- [--subtensor.register.no_output_in_place] [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]] [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB]
- [--logging.debug] [--logging.trace] [--logging.record_log] [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --wiz_vic.model_name WIZ_VIC.MODEL_NAME
- Name/path of model to load
- --wiz_vic.device WIZ_VIC.DEVICE
- Device to load model
- --wiz_vic.max_new_tokens WIZ_VIC.MAX_NEW_TOKENS
- Max tokens for model output.
- --wiz_vic.temperature WIZ_VIC.TEMPERATURE
- Sampling temperature of model
- --wiz_vic.greedy_decoding
- Whether to use greedy sampling or not (if not, uses multinomial sampling).
- --wiz_vic.do_sample Whether to use sampling or not (if not, uses greedy decoding).
- --wiz_vic.do_prompt_injection
- Whether to use a custom "system" prompt instead of the one sent by bittensor.
- --wiz_vic.system_prompt WIZ_VIC.SYSTEM_PROMPT
- What prompt to replace the system prompt with
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS [NEURON.BLACKLIST.HOTKEYS ...]]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes new worker threads to service requests up
- to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for
- testing)) If this option is set it overloads subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/neuron.py
deleted file mode 100644
index 288126317..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/neuron.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import bittensor
-from typing import List, Dict
-from transformers import AutoTokenizer, AutoModelForCausalLM
-
-class WizardVicunaMiner( bittensor.HuggingFaceMiner ):
- arg_prefix = "wiz_vic"
- system_label = ""
- assistant_label = "ASSISTANT:"
- user_label = "USER:"
-
- def load_tokenizer( self ):
- return AutoTokenizer.from_pretrained( self.config.wiz_vic.model_name, use_fast=False )
-
- def load_model( self ):
- return AutoModelForCausalLM.from_pretrained( self.config.wiz_vic.model_name, torch_dtype=torch.float16, low_cpu_mem_usage=True )
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
- history = self.process_history( messages )
- prompt = history + self.assistant_label
- input_ids = self.tokenizer.encode( prompt, return_tensors="pt" ).to( self.config.wiz_vic.device )
- output = self.model.generate(
- input_ids,
- max_length=input_ids.shape[1] + self.config.wiz_vic.max_new_tokens,
- temperature=self.config.wiz_vic.temperature,
- do_sample=self.config.wiz_vic.do_sample,
- pad_token_id=self.tokenizer.eos_token_id,
- )
- generation = self.tokenizer.decode( output[0][input_ids.shape[1]:], skip_special_tokens=True )
-
- bittensor.logging.debug( "Message: " + str( messages ) )
- bittensor.logging.debug( "Generation: " + str( generation) )
- return generation
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- WizardVicunaMiner().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/requirements.txt
deleted file mode 100644
index 33059ec77..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/huggingface/wizard_vicuna/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-transformers>=4.29.2
-accelerate
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/openai/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/openai/README.md
deleted file mode 100644
index c7b6ee866..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/openai/README.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# OpenAI Bittensor Miner
-This repository contains a Bittensor Miner that uses OpenAI's GPT-3.5-turbo model as its synapse. The miner connects to the Bittensor network, registers its wallet, and serves the GPT-3.5-turbo model to the network.
-
-## Prerequisites
-
-- Python 3.8+
-- OpenAI Python API (https://github.com/openai/openai)
-
-## Installation
-
-1. Clone the repository
-2. Install the required packages with `pip install -r requirements.txt`
-3. Set your OpenAI API key in the `api_key` argument when running the script
-
-For more configuration options related to the wallet, axon, subtensor, logging, and metagraph, please refer to the Bittensor documentation.
-
-## Example Usage
-
-To run the OpenAI Bittensor Miner with default settings, use the following command:
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/openai/requirements.txt
-python3 neurons/text/prompting/miners/openai/neuron.py --openai.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--openai.api_key OPENAI.API_KEY] [--openai.suffix OPENAI.SUFFIX] [--openai.max_tokens OPENAI.MAX_TOKENS]
- [--openai.temperature OPENAI.TEMPERATURE] [--openai.top_p OPENAI.TOP_P] [--openai.n OPENAI.N]
- [--openai.presence_penalty OPENAI.PRESENCE_PENALTY] [--openai.frequency_penalty OPENAI.FREQUENCY_PENALTY]
- [--openai.model_name OPENAI.MODEL_NAME] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --openai.api_key OPENAI.API_KEY
- openai api key
- --openai.suffix OPENAI.SUFFIX
- The suffix that comes after a completion of inserted text.
- --openai.max_tokens OPENAI.MAX_TOKENS
- The maximum number of tokens to generate in the completion.
- --openai.temperature OPENAI.TEMPERATURE
- Sampling temperature to use, between 0 and 2.
- --openai.top_p OPENAI.TOP_P
- Nucleus sampling parameter, top_p probability mass.
- --openai.n OPENAI.N How many completions to generate for each prompt.
- --openai.presence_penalty OPENAI.PRESENCE_PENALTY
- Penalty for tokens based on their presence in the text so far.
- --openai.frequency_penalty OPENAI.FREQUENCY_PENALTY
- Penalty for tokens based on their frequency in the text so far.
- --openai.model_name OPENAI.MODEL_NAME
- OpenAI model to use for completion.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/openai/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/openai/neuron.py
deleted file mode 100644
index 8726b8449..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/openai/neuron.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import openai
-import argparse
-import bittensor
-from typing import List, Dict
-import os
-import commune as c
-
-class OpenAIMiner( bittensor.BasePromptingMiner ):
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- assert config.openai.api_key != None, 'the miner requires passing --openai.api_key as an argument of the config.'
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- parser.add_argument('--openai.api_key', default='OPENAI_API_KEY', type=str, help='openai api key')
- parser.add_argument('--openai.suffix', type=str, default=None, help="The suffix that comes after a completion of inserted text.")
- parser.add_argument('--openai.max_tokens', type=int, default=256, help="The maximum number of tokens to generate in the completion.")
- parser.add_argument('--openai.temperature', type=float, default=0.7, help="Sampling temperature to use, between 0 and 2.")
- parser.add_argument('--openai.top_p', type=float, default=1, help="Nucleus sampling parameter, top_p probability mass.")
- parser.add_argument('--openai.n', type=int, default=1, help="How many completions to generate for each prompt.")
- parser.add_argument('--openai.presence_penalty', type=float, default=0, help="Penalty for tokens based on their presence in the text so far.")
- parser.add_argument('--openai.frequency_penalty', type=float, default=0, help="Penalty for tokens based on their frequency in the text so far.")
- parser.add_argument('--openai.model_name', type=str, default='gpt-3.5-turbo-0613', help="OpenAI model to use for completion.")
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- def __init__( self , config):
-
-
- super( OpenAIMiner, self ).__init__(config=config)
- self.config.openai.api_key = c.module('model.openai')().random_api_key()
- openai.api_key = self.config.openai.api_key
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
-
- try:
- resp = openai.ChatCompletion.create(
- model = self.config.openai.model_name,
- messages = messages,
- temperature = self.config.openai.temperature,
- max_tokens = self.config.openai.max_tokens,
- top_p = self.config.openai.top_p,
- frequency_penalty = self.config.openai.frequency_penalty,
- presence_penalty = self.config.openai.presence_penalty,
- n = self.config.openai.n,
- )['choices'][0]['message']['content']
- except Exception as e:
- c.print(e)
- self.config.openai.model_name = c.choice(['gpt-3.5-turbo-0613', 'gpt-3.5-turbo'])
- openai.api_key = c.module('model.openai')().random_api_key()
-
- return resp
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- OpenAIMiner().run()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/openai/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/openai/requirements.txt
deleted file mode 100644
index f0dd0aec5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/openai/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-openai
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/__init__.py
deleted file mode 100644
index 2b21e9c4b..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from .prompt_dataset import PromptDataset
-from .reward_dataset import HhRlhfDataset, RmStaticDataset, SHPDataset
-from .sft_dataset import DataCollatorForSupervisedDataset, SFTDataset, SupervisedDataset
-from .utils import is_rank_0
-
-__all__ = [
- 'RmStaticDataset', 'HhRlhfDataset', 'SHPDataset', 'is_rank_0', 'SFTDataset', 'SupervisedDataset',
- 'DataCollatorForSupervisedDataset', 'PromptDataset'
-]
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/prompt_dataset.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/prompt_dataset.py
deleted file mode 100644
index 4367a2c6f..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/prompt_dataset.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import copy
-import random
-from dataclasses import dataclass, field
-from typing import Callable, Dict, Sequence
-
-import torch
-import torch.distributed as dist
-import transformers
-from torch.utils.data import Dataset
-from tqdm import tqdm
-
-from colossalai.logging import get_dist_logger
-
-from .utils import is_rank_0, jload
-
-logger = get_dist_logger()
-
-
-class PromptDataset(Dataset):
- """Dataset for supervised fine-tuning."""
-
- def __init__(self, data_path: str, tokenizer: transformers.PreTrainedTokenizer, max_datasets_size: int = None):
- super(PromptDataset, self).__init__()
- self.prompt = []
- logger.info("Loading data...")
- list_data_dict = jload(data_path)
- logger.info(f"Loaded {len(list_data_dict)} examples.")
-
- if max_datasets_size is not None:
- logger.info(f"Limiting dataset to {max_datasets_size} examples.")
- list_data_dict = list_data_dict[:max_datasets_size]
-
- for data_dict in list_data_dict:
- token = tokenizer(data_dict["instruction"],
- return_tensors='pt',
- max_length=96,
- padding='max_length',
- truncation=True)
- for idx in token['input_ids']:
- self.prompt.append(idx.to(torch.cuda.current_device()))
-
- def __len__(self):
- return len(self.prompt)
-
- def __getitem__(self, i) -> Dict[str, torch.Tensor]:
- return self.prompt[i]
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/reward_dataset.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/reward_dataset.py
deleted file mode 100644
index 51aa0ec4c..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/reward_dataset.py
+++ /dev/null
@@ -1,167 +0,0 @@
-from typing import Callable
-
-from torch.utils.data import Dataset
-from tqdm import tqdm
-
-from .utils import is_rank_0
-
-
-# Dahaos/rm-static
-class RmStaticDataset(Dataset):
- """
- Dataset for reward model
-
- Args:
- dataset: dataset for reward model
- tokenizer: tokenizer for reward model
- max_length: max length of input
- special_token: special token at the end of sentence
- """
-
- def __init__(self, dataset, tokenizer: Callable, max_length: int, special_token=None) -> None:
- super().__init__()
- self.chosen = []
- self.reject = []
- if special_token is None:
- self.end_token = tokenizer.eos_token
- else:
- self.end_token = special_token
- for data in tqdm(dataset, disable=not is_rank_0()):
- prompt = data['prompt']
-
- chosen = prompt + data['chosen'] + self.end_token
- chosen_token = tokenizer(chosen,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
- self.chosen.append({
- "input_ids": chosen_token['input_ids'],
- "attention_mask": chosen_token['attention_mask']
- })
-
- reject = prompt + data['rejected'] + self.end_token
- reject_token = tokenizer(reject,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
- self.reject.append({
- "input_ids": reject_token['input_ids'],
- "attention_mask": reject_token['attention_mask']
- })
-
- def __len__(self):
- length = len(self.chosen)
- return length
-
- def __getitem__(self, idx):
- return self.chosen[idx]["input_ids"], self.chosen[idx]["attention_mask"], self.reject[idx][
- "input_ids"], self.reject[idx]["attention_mask"]
-
-# Dahoas/filtered-SHP
-class SHPDataset(Dataset):
- """
- Dataset for reward model
-
- Args:
- dataset: dataset for reward model
- tokenizer: tokenizer for reward model
- max_length: max length of input
- special_token: special token at the end of sentence
- """
-
- def __init__(self, dataset, tokenizer: Callable, max_length: int, special_token=None) -> None:
- super().__init__()
- self.chosen = []
- self.reject = []
- if special_token is None:
- self.end_token = tokenizer.eos_token
- else:
- self.end_token = special_token
- for data in tqdm(dataset, disable=not is_rank_0()):
- prompt = data['prompt']
-
- chosen = prompt + data['chosen'] + self.end_token
- chosen_token = tokenizer(chosen,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
- self.chosen.append({
- "input_ids": chosen_token['input_ids'],
- "attention_mask": chosen_token['attention_mask']
- })
-
- reject = prompt + data['rejected'] + self.end_token
- reject_token = tokenizer(reject,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
- self.reject.append({
- "input_ids": reject_token['input_ids'],
- "attention_mask": reject_token['attention_mask']
- })
-
- def __len__(self):
- length = len(self.chosen)
- return length
-
- def __getitem__(self, idx):
- return self.chosen[idx]["input_ids"], self.chosen[idx]["attention_mask"], self.reject[idx][
- "input_ids"], self.reject[idx]["attention_mask"]
-
-
-
-
-# Anthropic/hh-rlhf
-class HhRlhfDataset(Dataset):
- """
- Dataset for reward model
-
- Args:
- dataset: dataset for reward model
- tokenizer: tokenizer for reward model
- max_length: max length of input
- special_token: special token at the end of sentence
- """
-
- def __init__(self, dataset, tokenizer: Callable, max_length: int, special_token=None) -> None:
- super().__init__()
- self.chosen = []
- self.reject = []
- if special_token is None:
- self.end_token = tokenizer.eos_token
- else:
- self.end_token = special_token
- for data in tqdm(dataset, disable=not is_rank_0()):
- chosen = data['chosen'] + self.end_token
- chosen_token = tokenizer(chosen,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
- self.chosen.append({
- "input_ids": chosen_token['input_ids'],
- "attention_mask": chosen_token['attention_mask']
- })
-
- reject = data['rejected'] + self.end_token
- reject_token = tokenizer(reject,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
- self.reject.append({
- "input_ids": reject_token['input_ids'],
- "attention_mask": reject_token['attention_mask']
- })
-
- def __len__(self):
- length = len(self.chosen)
- return length
-
- def __getitem__(self, idx):
- return self.chosen[idx]["input_ids"], self.chosen[idx]["attention_mask"], self.reject[idx][
- "input_ids"], self.reject[idx]["attention_mask"]
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/sft_dataset.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/sft_dataset.py
deleted file mode 100644
index 76ae6b158..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/sft_dataset.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright 2023 Rohan Taori, Ishaan Gulrajani, Tianyi Zhang, Yann Dubois, Xuechen Li
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import copy
-import random
-from dataclasses import dataclass, field
-from typing import Callable, Dict, Sequence
-
-import torch
-import torch.distributed as dist
-import transformers
-from torch.utils.data import Dataset
-from tqdm import tqdm
-
-from colossalai.logging import get_dist_logger
-
-from .utils import is_rank_0, jload
-
-logger = get_dist_logger()
-
-IGNORE_INDEX = -100
-PROMPT_DICT = {
- "prompt_input":
- ("Below is an instruction that describes a task, paired with an input that provides further context. "
- "Write a response that appropriately completes the request.\n\n"
- "### Instruction:\n{instruction}\n\n### Input:\n{input}\n\n### Response:"),
- "prompt_no_input": ("Below is an instruction that describes a task. "
- "Write a response that appropriately completes the request.\n\n"
- "### Instruction:\n{instruction}\n\n### Response:"),
-}
-
-
-class SFTDataset(Dataset):
- """
- Dataset for sft model
-
- Args:
- dataset: dataset for supervised model
- tokenizer: tokenizer for supervised model
- max_length: max length of input
- """
-
- def __init__(self, dataset, tokenizer: Callable, max_length: int = 512) -> None:
- super().__init__()
- # self.prompts = []
- self.input_ids = []
-
- for data in tqdm(dataset, disable=not is_rank_0()):
- prompt = data['prompt'] + data['completion'] + "<|endoftext|>"
- prompt_token = tokenizer(prompt,
- max_length=max_length,
- padding="max_length",
- truncation=True,
- return_tensors="pt")
-
- # self.prompts.append(prompt_token)s
- self.input_ids.append(prompt_token)
- self.labels = copy.deepcopy(self.input_ids)
-
- def __len__(self):
- length = len(self.prompts)
- return length
-
- def __getitem__(self, idx):
- # dict(input_ids=self.input_ids[i], labels=self.labels[i])
- return dict(input_ids=self.input_ids[idx], labels=self.labels[idx])
- # return dict(self.prompts[idx], self.prompts[idx])
-
-
-def _tokenize_fn(strings: Sequence[str], tokenizer: transformers.PreTrainedTokenizer) -> Dict:
- """Tokenize a list of strings."""
- tokenized_list = [
- tokenizer(
- text,
- return_tensors="pt",
- padding="longest",
- max_length=tokenizer.model_max_length,
- truncation=True,
- ) for text in strings
- ]
- input_ids = labels = [tokenized.input_ids[0] for tokenized in tokenized_list]
- input_ids_lens = labels_lens = [
- tokenized.input_ids.ne(tokenizer.pad_token_id).sum().item() for tokenized in tokenized_list
- ]
- return dict(
- input_ids=input_ids,
- labels=labels,
- input_ids_lens=input_ids_lens,
- labels_lens=labels_lens,
- )
-
-
-def preprocess(
- sources: Sequence[str],
- targets: Sequence[str],
- tokenizer: transformers.PreTrainedTokenizer,
-) -> Dict:
- """Preprocess the data by tokenizing."""
- examples = [s + t for s, t in zip(sources, targets)]
- examples_tokenized, sources_tokenized = [_tokenize_fn(strings, tokenizer) for strings in (examples, sources)]
- input_ids = examples_tokenized["input_ids"]
- labels = copy.deepcopy(input_ids)
- for label, source_len in zip(labels, sources_tokenized["input_ids_lens"]):
- label[:source_len] = IGNORE_INDEX
- return dict(input_ids=input_ids, labels=labels)
-
-
-class SupervisedDataset(Dataset):
- """Dataset for supervised fine-tuning."""
-
- def __init__(self, data_path: str, tokenizer: transformers.PreTrainedTokenizer, max_datasets_size: int = None):
- super(SupervisedDataset, self).__init__()
- logger.info("Loading data...")
- list_data_dict = jload(data_path)
- logger.info(f"Loaded {len(list_data_dict)} examples.")
-
- if max_datasets_size is not None:
- logger.info(f"Limiting dataset to {max_datasets_size} examples.")
- list_data_dict = list_data_dict[:max_datasets_size]
-
- logger.info("Formatting inputs...")
- prompt_input, prompt_no_input = PROMPT_DICT["prompt_input"], PROMPT_DICT["prompt_no_input"]
- sources = [
- prompt_input.format_map(example) if example.get("input", "") != "" else prompt_no_input.format_map(example)
- for example in list_data_dict
- ]
- targets = [f"{example['output']}{tokenizer.eos_token}" for example in list_data_dict]
-
- logger.info("Tokenizing inputs... This may take some time...")
- data_dict = preprocess(sources, targets, tokenizer)
-
- self.input_ids = data_dict["input_ids"]
- self.labels = data_dict["labels"]
-
- def __len__(self):
- return len(self.input_ids)
-
- def __getitem__(self, i) -> Dict[str, torch.Tensor]:
- return dict(input_ids=self.input_ids[i], labels=self.labels[i])
-
-
-@dataclass
-class DataCollatorForSupervisedDataset(object):
- """Collate examples for supervised fine-tuning."""
-
- tokenizer: transformers.PreTrainedTokenizer
-
- def __call__(self, instances: Sequence[Dict]) -> Dict[str, torch.Tensor]:
- input_ids, labels = tuple([instance[key] for instance in instances] for key in ("input_ids", "labels"))
- input_ids = torch.nn.utils.rnn.pad_sequence(input_ids,
- batch_first=True,
- padding_value=self.tokenizer.pad_token_id)
- labels = torch.nn.utils.rnn.pad_sequence(labels, batch_first=True, padding_value=IGNORE_INDEX)
- return dict(
- input_ids=input_ids,
- labels=labels,
- attention_mask=input_ids.ne(self.tokenizer.pad_token_id),
- )
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/utils.py
deleted file mode 100644
index f37fce67a..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/dataset/utils.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import io
-import json
-
-import torch.distributed as dist
-
-
-def is_rank_0() -> bool:
- return not dist.is_initialized() or dist.get_rank() == 0
-
-
-def _make_r_io_base(f, mode: str):
- if not isinstance(f, io.IOBase):
- f = open(f, mode=mode)
- return f
-
-
-def jload(f, mode="r"):
- """Load a .json file into a dictionary."""
- f = _make_r_io_base(f, mode)
- jdict = json.load(f)
- f.close()
- return jdict
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/__init__.py
deleted file mode 100644
index 39ca7576b..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .base import Experience, ExperienceMaker
-from .naive import NaiveExperienceMaker
-
-__all__ = ['Experience', 'ExperienceMaker', 'NaiveExperienceMaker']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/base.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/base.py
deleted file mode 100644
index 61fd4f674..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/base.py
+++ /dev/null
@@ -1,77 +0,0 @@
-from abc import ABC, abstractmethod
-from dataclasses import dataclass
-from typing import Optional
-
-import torch
-import torch.nn as nn
-from coati.models.base import Actor
-
-
-@dataclass
-class Experience:
- """Experience is a batch of data.
- These data should have the the sequence length and number of actions.
- Left padding for sequences is applied.
-
- Shapes of each tensor:
- sequences: (B, S)
- action_log_probs: (B, A)
- values: (B)
- reward: (B)
- advatanges: (B)
- attention_mask: (B, S)
- action_mask: (B, A)
-
- "A" is the number of actions.
- """
- sequences: torch.Tensor
- action_log_probs: torch.Tensor
- values: torch.Tensor
- reward: torch.Tensor
- advantages: torch.Tensor
- attention_mask: Optional[torch.LongTensor]
- action_mask: Optional[torch.BoolTensor]
-
- @torch.no_grad()
- def to_device(self, device: torch.device) -> None:
- self.sequences = self.sequences.to(device)
- self.action_log_probs = self.action_log_probs.to(device)
- self.values = self.values.to(device)
- self.reward = self.reward.to(device)
- self.advantages = self.advantages.to(device)
- if self.attention_mask is not None:
- self.attention_mask = self.attention_mask.to(device)
- if self.action_mask is not None:
- self.action_mask = self.action_mask.to(device)
-
- def pin_memory(self):
- self.sequences = self.sequences.pin_memory()
- self.action_log_probs = self.action_log_probs.pin_memory()
- self.values = self.values.pin_memory()
- self.reward = self.reward.pin_memory()
- self.advantages = self.advantages.pin_memory()
- if self.attention_mask is not None:
- self.attention_mask = self.attention_mask.pin_memory()
- if self.action_mask is not None:
- self.action_mask = self.action_mask.pin_memory()
- return self
-
-
-class ExperienceMaker(ABC):
-
- def __init__(self,
- actor: Actor,
- critic: nn.Module,
- reward_model: nn.Module,
- initial_model: Actor,
- kl_coef: float = 0.1) -> None:
- super().__init__()
- self.actor = actor
- self.critic = critic
- self.reward_model = reward_model
- self.initial_model = initial_model
- self.kl_coef = kl_coef
-
- @abstractmethod
- def make_experience(self, input_ids: torch.Tensor, **generate_kwargs) -> Experience:
- pass
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/naive.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/naive.py
deleted file mode 100644
index 94546eeb2..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/experience_maker/naive.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import torch
-from coati.models.utils import compute_reward, normalize
-
-from .base import Experience, ExperienceMaker
-
-
-class NaiveExperienceMaker(ExperienceMaker):
- """
- Naive experience maker.
- """
-
- @torch.no_grad()
- def make_experience(self, input_ids: torch.Tensor, **generate_kwargs) -> Experience:
- self.actor.eval()
- self.critic.eval()
- self.initial_model.eval()
- self.reward_model.eval()
-
- sequences, attention_mask, action_mask = self.actor.generate(input_ids,
- return_action_mask=True,
- **generate_kwargs)
- num_actions = action_mask.size(1)
-
- action_log_probs = self.actor(sequences, num_actions, attention_mask)
- base_action_log_probs = self.initial_model(sequences, num_actions, attention_mask)
- value = self.critic(sequences, action_mask, attention_mask)
- r = self.reward_model(sequences, attention_mask)
- reward = compute_reward(r, self.kl_coef, action_log_probs, base_action_log_probs, action_mask=action_mask)
-
- advantage = reward - value
- # TODO(ver217): maybe normalize adv
- if advantage.ndim == 1:
- advantage = advantage.unsqueeze(-1)
-
- return Experience(sequences, action_log_probs, value, reward, advantage, attention_mask, action_mask)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/__init__.py
deleted file mode 100644
index 7489b2e87..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .base import Actor, Critic, RewardModel
-from .loss import LogExpLoss, LogSigLoss, PolicyLoss, PPOPtxActorLoss, ValueLoss
-
-__all__ = ['Actor', 'Critic', 'RewardModel', 'PolicyLoss', 'ValueLoss', 'PPOPtxActorLoss', 'LogSigLoss', 'LogExpLoss']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/actor.py
deleted file mode 100644
index be9e9abf1..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/actor.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Optional
-
-from transformers import AutoConfig, AutoModelForCausalLM
-
-
-from base import Actor
-
-
-class AutoActor(Actor):
- """
- Auto Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (AutoConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[AutoConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = AutoModelForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = AutoModelForCausalLM(config)
- else:
- model = AutoModelForCausalLM(AutoConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/critic.py
deleted file mode 100644
index fa3d698f4..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/critic.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import AutoConfig, AutoModel
-from ..base import Critic
-
-
-class AutoCritic(Critic):
- """
- Auto Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (AutoConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[AutoConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- **kwargs) -> None:
- if pretrained is not None:
- model = AutoModel.from_pretrained(pretrained)
- elif config is not None:
- model = AutoModel(config)
- else:
- model = AutoModel(AutoConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.word_embed_proj_dim, 1)
- super().__init__(model, value_head, lora_rank, lora_train_bias, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/lm.py
deleted file mode 100644
index 6375429f8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/lm.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from typing import Optional
-
-from transformers import AutoConfig, AutoModelForCausalLM
-from ..base import LM
-
-
-class AutoLM(LM):
- """
- Auto language model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (AutoConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[AutoConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = AutoModelForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = AutoModelForCausalLM(config)
- else:
- model = AutoModelForCausalLM(AutoConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
-
- def forward(self, input_ids, attention_mask=None, labels=None, **kwargs):
- return self.model(input_ids, attention_mask=attention_mask, labels=labels, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/reward_model.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/reward_model.py
deleted file mode 100644
index bbca36a48..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/auto/reward_model.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import AutoConfig, AutoModel
-from ..base import RewardModel
-
-
-class AutoRM(RewardModel):
- """
- Auto Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (AutoConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[AutoConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = AutoModel.from_pretrained(pretrained)
- elif config is not None:
- model = AutoModel(config)
- else:
- model = AutoModel(AutoConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- value_head = nn.Linear(model.config.word_embed_proj_dim, 1)
- value_head.weight.data.normal_(mean=0.0, std=1 / (model.config.word_embed_proj_dim + 1))
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/__init__.py
deleted file mode 100644
index 7cf82309a..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .actor import Actor
-from .critic import Critic
-from .lm import LM
-from .reward_model import RewardModel
-
-__all__ = ['Actor', 'Critic', 'RewardModel', 'LM']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/actor.py
deleted file mode 100644
index 71fbf7bba..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/actor.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from typing import Optional, Tuple, Union
-
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-from ..generation import generate
-from ..lora import LoRAModule
-from ..utils import log_probs_from_logits
-
-
-class Actor(LoRAModule):
- """
- Actor model base class.
-
- Args:
- model (nn.Module): Actor Model.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self, model: nn.Module, lora_rank: int = 0, lora_train_bias: str = 'none') -> None:
- super().__init__(lora_rank=lora_rank, lora_train_bias=lora_train_bias)
- self.model = model
- self.convert_to_lora()
-
- @torch.no_grad()
- def generate(
- self,
- input_ids: torch.Tensor,
- return_action_mask: bool = True,
- **kwargs
- ) -> Union[Tuple[torch.LongTensor, torch.LongTensor], Tuple[torch.LongTensor, torch.LongTensor, torch.BoolTensor]]:
- sequences = generate(self.model, input_ids, **kwargs)
- attention_mask = None
- pad_token_id = kwargs.get('pad_token_id', None)
- if pad_token_id is not None:
- attention_mask = sequences.not_equal(pad_token_id).to(dtype=torch.long, device=sequences.device)
- if not return_action_mask:
- return sequences, attention_mask, None
- input_len = input_ids.size(1)
- eos_token_id = kwargs.get('eos_token_id', None)
- if eos_token_id is None:
- action_mask = torch.ones_like(sequences, dtype=torch.bool)
- else:
- # left padding may be applied, only mask action
- action_mask = (sequences[:, input_len:] == eos_token_id).cumsum(dim=-1) == 0
- action_mask = F.pad(action_mask, (1 + input_len, -1), value=True) # include eos token and input
- action_mask[:, :input_len] = False
- action_mask = action_mask[:, 1:]
- return sequences, attention_mask, action_mask[:, -(sequences.size(1) - input_len):]
-
- def forward(self,
- sequences: torch.LongTensor,
- num_actions: int,
- attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- """Returns action log probs
- """
- output = self.model(sequences, attention_mask=attention_mask)
- logits = output['logits']
- log_probs = log_probs_from_logits(logits[:, :-1, :], sequences[:, 1:])
- return log_probs[:, -num_actions:]
-
- def get_base_model(self):
- return self.model
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/critic.py
deleted file mode 100644
index e68a743a7..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/critic.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-
-from ..lora import LoRAModule
-from ..utils import masked_mean
-
-
-class Critic(LoRAModule):
- """
- Critic model base class.
-
- Args:
- model (nn.Module): Critic model.
- value_head (nn.Module): Value head to get value.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(
- self,
- model: nn.Module,
- value_head: nn.Module,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- use_action_mask: bool = False,
- ) -> None:
-
- super().__init__(lora_rank=lora_rank, lora_train_bias=lora_train_bias)
- self.model = model
- self.value_head = value_head
- self.use_action_mask = use_action_mask
- self.convert_to_lora()
-
- def forward(self,
- sequences: torch.LongTensor,
- action_mask: Optional[torch.Tensor] = None,
- attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- outputs = self.model(sequences, attention_mask=attention_mask)
- last_hidden_states = outputs['last_hidden_state']
-
- values = self.value_head(last_hidden_states).squeeze(-1)
-
- if action_mask is not None and self.use_action_mask:
- num_actions = action_mask.size(1)
- prompt_mask = attention_mask[:, :-num_actions]
- values = values[:, :-num_actions]
- value = masked_mean(values, prompt_mask, dim=1)
- return value
-
- values = values[:, :-1]
- value = values.mean(dim=1)
- return value
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/lm.py
deleted file mode 100644
index e32ba4253..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/lm.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from typing import Optional, Tuple, Union
-
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-from ..generation import generate
-from .actor import Actor
-
-
-class LM(Actor):
- """
- Language model base class.
-
- Args:
- model (nn.Module): Language Model.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self, model: nn.Module, lora_rank: int = 0, lora_train_bias: str = 'none') -> None:
- super().__init__(model=model, lora_rank=lora_rank, lora_train_bias=lora_train_bias)
-
- def forward(self, sequences: torch.LongTensor, attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- """Returns output log probs
- """
- output = self.model(sequences, attention_mask=attention_mask)
- logits = output['logits']
- log_probs = F.log_softmax(logits, dim=-1)
- return log_probs
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/reward_model.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/reward_model.py
deleted file mode 100644
index ce8c0a1d3..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/base/reward_model.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-
-from ..lora import LoRAModule
-
-
-class RewardModel(LoRAModule):
- """
- Reward model base class.
-
- Args:
- model (nn.Module): Reward model.
- value_head (nn.Module): Value head to get reward score.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- model: nn.Module,
- value_head: Optional[nn.Module] = None,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- super().__init__(lora_rank=lora_rank, lora_train_bias=lora_train_bias)
- self.model = model
- self.convert_to_lora()
-
- if value_head is not None:
- if value_head.out_features != 1:
- raise ValueError("The value head of reward model's output dim should be 1!")
- self.value_head = value_head
- else:
- self.value_head = nn.Linear(model.config.n_embd, 1)
-
- def forward(self, sequences: torch.LongTensor, attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- outputs = self.model(sequences, attention_mask=attention_mask)
- last_hidden_states = outputs['last_hidden_state']
- values = self.value_head(last_hidden_states)[:, :-1]
- value = values.mean(dim=1).squeeze(1) # ensure shape is (B)
- return value
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/__init__.py
deleted file mode 100644
index 39dfe036a..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .bloom_actor import BLOOMActor
-from .bloom_critic import BLOOMCritic
-from .bloom_lm import BLOOMLM
-from .bloom_rm import BLOOMRM
-
-__all__ = ['BLOOMActor', 'BLOOMCritic', 'BLOOMRM', 'BLOOMLM']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_actor.py
deleted file mode 100644
index d7577f096..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_actor.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Optional
-
-import torch
-from transformers import BloomConfig, BloomForCausalLM, BloomModel
-
-from ..base import Actor
-
-
-class BLOOMActor(Actor):
- """
- BLOOM Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (BloomConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: str = None,
- config: Optional[BloomConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = BloomForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = BloomForCausalLM(config)
- else:
- model = BloomForCausalLM(BloomConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_critic.py
deleted file mode 100644
index a32fb2e10..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_critic.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-from transformers import BloomConfig, BloomForCausalLM, BloomModel
-
-from ..base import Critic
-
-
-class BLOOMCritic(Critic):
- """
- BLOOM Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (BloomConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: str = None,
- config: Optional[BloomConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- **kwargs) -> None:
- if pretrained is not None:
- model = BloomModel.from_pretrained(pretrained)
- elif config is not None:
- model = BloomModel(config)
- else:
- model = BloomModel(BloomConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.hidden_size, 1)
- super().__init__(model, value_head, lora_rank, lora_train_bias, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_lm.py
deleted file mode 100644
index e4184fcd0..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_lm.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-import torch
-from transformers import BloomConfig, BloomForCausalLM, BloomModel
-
-from ..base import LM
-
-
-class BLOOMLM(LM):
- """
- BLOOM language model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (BloomConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: str = None,
- config: Optional[BloomConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = BloomForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = BloomForCausalLM(config)
- else:
- model = BloomForCausalLM(BloomConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
-
- def forward(self, input_ids, attention_mask=None, labels=None, **kwargs):
- return self.model(input_ids, attention_mask=attention_mask, labels=labels, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_rm.py
deleted file mode 100644
index 22cfab441..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/bloom/bloom_rm.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import BloomConfig, BloomForCausalLM, BloomModel
-
-from ..base import RewardModel
-
-
-class BLOOMRM(RewardModel):
- """
- BLOOM Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (BloomConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: str = None,
- config: Optional[BloomConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = BloomModel.from_pretrained(pretrained)
- elif config is not None:
- model = BloomModel(config)
- else:
- model = BloomModel(BloomConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.hidden_size, 1)
- value_head.weight.data.normal_(mean=0.0, std=1 / (model.config.hidden_size + 1))
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/__init__.py
deleted file mode 100644
index b66888f34..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .deberta_critic import DebertaCritic
-from .deberta_rm import DebertaRM
-
-__all__ = ['DebertaCritic', 'DebertaRM']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/deberta_critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/deberta_critic.py
deleted file mode 100644
index e84c1dbd8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/deberta_critic.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import DebertaV2Config, DebertaV2Model
-
-from ..base import Critic
-
-
-class DebertaCritic(Critic):
- """
- Deberta Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (DebertaV2Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the LO-RA decomposition.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[DebertaV2Config] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = DebertaV2Model.from_pretrained(pretrained)
- elif config is not None:
- model = DebertaV2Model(config)
- else:
- model = DebertaV2Model(DebertaV2Config())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.hidden_size, 1)
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/deberta_rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/deberta_rm.py
deleted file mode 100644
index 2448c879e..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/deberta/deberta_rm.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import DebertaV2Config, DebertaV2Model
-
-from ..base import RewardModel
-
-
-class DebertaRM(RewardModel):
- """
- Deberta Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (DebertaV2Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the LO-RA decomposition.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: str = None,
- config: Optional[DebertaV2Config] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = DebertaV2Model.from_pretrained(pretrained)
- elif config is not None:
- model = DebertaV2Model(config)
- else:
- model = DebertaV2Model(DebertaV2Config())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.hidden_size, 1)
- value_head.weight.data.normal_(mean=0.0, std=1 / (model.config.hidden_size + 1))
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/generation.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/generation.py
deleted file mode 100644
index eb30c36d0..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/generation.py
+++ /dev/null
@@ -1,146 +0,0 @@
-from typing import Any, Callable, Optional
-
-import torch
-import torch.distributed as dist
-import torch.nn as nn
-
-try:
- from transformers.generation_logits_process import (
- LogitsProcessorList,
- TemperatureLogitsWarper,
- TopKLogitsWarper,
- TopPLogitsWarper,
- )
-except ImportError:
- from transformers.generation import LogitsProcessorList, TemperatureLogitsWarper, TopKLogitsWarper, TopPLogitsWarper
-
-
-def prepare_logits_processor(top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- temperature: Optional[float] = None) -> LogitsProcessorList:
- processor_list = LogitsProcessorList()
- if temperature is not None and temperature != 1.0:
- processor_list.append(TemperatureLogitsWarper(temperature))
- if top_k is not None and top_k != 0:
- processor_list.append(TopKLogitsWarper(top_k))
- if top_p is not None and top_p < 1.0:
- processor_list.append(TopPLogitsWarper(top_p))
- return processor_list
-
-
-def _is_sequence_finished(unfinished_sequences: torch.Tensor) -> bool:
- if dist.is_initialized() and dist.get_world_size() > 1:
- # consider DP
- unfinished_sequences = unfinished_sequences.clone()
- dist.all_reduce(unfinished_sequences)
- return unfinished_sequences.max() == 0
-
-
-def sample(model: nn.Module,
- input_ids: torch.Tensor,
- max_length: int,
- early_stopping: bool = False,
- eos_token_id: Optional[int] = None,
- pad_token_id: Optional[int] = None,
- top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- temperature: Optional[float] = None,
- prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,
- update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,
- **model_kwargs) -> torch.Tensor:
- if input_ids.size(1) >= max_length:
- return input_ids
-
- logits_processor = prepare_logits_processor(top_k, top_p, temperature)
- unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1)
-
- for _ in range(input_ids.size(1), max_length):
- model_inputs = prepare_inputs_fn(input_ids, **model_kwargs) if prepare_inputs_fn is not None else {
- 'input_ids': input_ids
- }
- outputs = model(**model_inputs)
-
- next_token_logits = outputs['logits'][:, -1, :]
- # pre-process distribution
- next_token_logits = logits_processor(input_ids, next_token_logits)
- # sample
- probs = torch.softmax(next_token_logits, dim=-1, dtype=torch.float)
- next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1)
-
- # finished sentences should have their next token be a padding token
- if eos_token_id is not None:
- if pad_token_id is None:
- raise ValueError("If `eos_token_id` is defined, make sure that `pad_token_id` is defined.")
- next_tokens = next_tokens * unfinished_sequences + pad_token_id * (1 - unfinished_sequences)
-
- # update generated ids, model inputs for next step
- input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)
- if update_model_kwargs_fn is not None:
- model_kwargs = update_model_kwargs_fn(outputs, **model_kwargs)
-
- # if eos_token was found in one sentence, set sentence to finished
- if eos_token_id is not None:
- unfinished_sequences = unfinished_sequences.mul((next_tokens != eos_token_id).long())
-
- # stop when each sentence is finished if early_stopping=True
- if early_stopping and _is_sequence_finished(unfinished_sequences):
- break
-
- return input_ids
-
-
-def generate(model: nn.Module,
- input_ids: torch.Tensor,
- max_length: int,
- num_beams: int = 1,
- do_sample: bool = True,
- early_stopping: bool = False,
- eos_token_id: Optional[int] = None,
- pad_token_id: Optional[int] = None,
- top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- temperature: Optional[float] = None,
- prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,
- update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,
- **model_kwargs) -> torch.Tensor:
- """Generate token sequence. The returned sequence is input_ids + generated_tokens.
-
- Args:
- model (nn.Module): model
- input_ids (torch.Tensor): input sequence
- max_length (int): max length of the returned sequence
- num_beams (int, optional): number of beams. Defaults to 1.
- do_sample (bool, optional): whether to do sample. Defaults to True.
- early_stopping (bool, optional): if True, the sequence length may be smaller than max_length due to finding eos. Defaults to False.
- eos_token_id (Optional[int], optional): end of sequence token id. Defaults to None.
- pad_token_id (Optional[int], optional): pad token id. Defaults to None.
- top_k (Optional[int], optional): the number of highest probability vocabulary tokens to keep for top-k-filtering. Defaults to None.
- top_p (Optional[float], optional): If set to float < 1, only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation. Defaults to None.
- temperature (Optional[float], optional): The value used to module the next token probabilities. Defaults to None.
- prepare_inputs_fn (Optional[Callable[[torch.Tensor, Any], dict]], optional): Function to preprocess model inputs. Arguments of this function should be input_ids and model_kwargs. Defaults to None.
- update_model_kwargs_fn (Optional[Callable[[dict, Any], dict]], optional): Function to update model_kwargs based on outputs. Arguments of this function should be outputs and model_kwargs. Defaults to None.
- """
- is_greedy_gen_mode = ((num_beams == 1) and do_sample is False)
- is_sample_gen_mode = ((num_beams == 1) and do_sample is True)
- is_beam_gen_mode = ((num_beams > 1) and do_sample is False)
- if is_greedy_gen_mode:
- # run greedy search
- raise NotImplementedError
- elif is_sample_gen_mode:
- # run sample
- return sample(model,
- input_ids,
- max_length,
- early_stopping=early_stopping,
- eos_token_id=eos_token_id,
- pad_token_id=pad_token_id,
- top_k=top_k,
- top_p=top_p,
- temperature=temperature,
- prepare_inputs_fn=prepare_inputs_fn,
- update_model_kwargs_fn=update_model_kwargs_fn,
- **model_kwargs)
- elif is_beam_gen_mode:
- raise NotImplementedError
- else:
- raise ValueError("Unsupported generation mode")
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/generation_utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/generation_utils.py
deleted file mode 100644
index c7bc1b383..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/generation_utils.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from typing import Optional
-
-import torch
-
-
-def gpt_prepare_inputs_fn(input_ids: torch.Tensor, past: Optional[torch.Tensor] = None, **kwargs) -> dict:
- token_type_ids = kwargs.get("token_type_ids", None)
- # only last token for inputs_ids if past is defined in kwargs
- if past:
- input_ids = input_ids[:, -1].unsqueeze(-1)
- if token_type_ids is not None:
- token_type_ids = token_type_ids[:, -1].unsqueeze(-1)
-
- attention_mask = kwargs.get("attention_mask", None)
- position_ids = kwargs.get("position_ids", None)
-
- if attention_mask is not None and position_ids is None:
- # create position_ids on the fly for batch generation
- position_ids = attention_mask.long().cumsum(-1) - 1
- position_ids.masked_fill_(attention_mask == 0, 1)
- if past:
- position_ids = position_ids[:, -1].unsqueeze(-1)
- else:
- position_ids = None
- return {
- "input_ids": input_ids,
- "past_key_values": past,
- "use_cache": kwargs.get("use_cache"),
- "position_ids": position_ids,
- "attention_mask": attention_mask,
- "token_type_ids": token_type_ids,
- }
-
-
-def update_model_kwargs_fn(outputs: dict, **model_kwargs) -> dict:
- if "past_key_values" in outputs:
- model_kwargs["past"] = outputs["past_key_values"]
- else:
- model_kwargs["past"] = None
-
- # update token_type_ids with last value
- if "token_type_ids" in model_kwargs:
- token_type_ids = model_kwargs["token_type_ids"]
- model_kwargs["token_type_ids"] = torch.cat([token_type_ids, token_type_ids[:, -1].unsqueeze(-1)], dim=-1)
-
- # update attention mask
- if "attention_mask" in model_kwargs:
- attention_mask = model_kwargs["attention_mask"]
- model_kwargs["attention_mask"] = torch.cat(
- [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1)
-
- return model_kwargs
-
-
-def opt_prepare_inputs_fn(input_ids: torch.Tensor,
- past: Optional[torch.Tensor] = None,
- attention_mask: Optional[torch.Tensor] = None,
- use_cache: Optional[bool] = None,
- **kwargs) -> dict:
- # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly
- if attention_mask is None:
- attention_mask = input_ids.new_ones(input_ids.shape)
-
- if past:
- input_ids = input_ids[:, -1:]
- # first step, decoder_cached_states are empty
- return {
- "input_ids": input_ids, # encoder_outputs is defined. input_ids not needed
- "attention_mask": attention_mask,
- "past_key_values": past,
- "use_cache": use_cache,
- }
-
-
-def bloom_prepare_inputs_fn(input_ids: torch.Tensor,
- past: Optional[torch.Tensor] = None,
- attention_mask: Optional[torch.Tensor] = None,
- use_cache: Optional[bool] = None,
- **kwargs) -> dict:
- # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly
- if attention_mask is None:
- attention_mask = input_ids.new_ones(input_ids.shape)
-
- if past:
- input_ids = input_ids[:, -1:]
- # first step, decoder_cached_states are empty
- return {
- "input_ids": input_ids, # encoder_outputs is defined. input_ids not needed
- "attention_mask": attention_mask,
- "past_key_values": past,
- "use_cache": use_cache,
- }
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/__init__.py
deleted file mode 100644
index 9dc68e375..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .gpt_actor import GPTActor
-from .gpt_critic import GPTCritic
-from .gpt_lm import GPTLM
-from .gpt_rm import GPTRM
-
-__all__ = ['GPTActor', 'GPTCritic', 'GPTRM', 'GPTLM']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_actor.py
deleted file mode 100644
index 6a53ad40b..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_actor.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Optional
-
-from transformers.models.gpt2.configuration_gpt2 import GPT2Config
-from transformers.models.gpt2.modeling_gpt2 import GPT2LMHeadModel
-
-from ..base import Actor
-
-
-class GPTActor(Actor):
- """
- GPT Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (GPT2Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the LoRa layer.
- lora_train_bias (str): Bias training strategy for the LoRa layer.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[GPT2Config] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = GPT2LMHeadModel.from_pretrained(pretrained)
- elif config is not None:
- model = GPT2LMHeadModel(config)
- else:
- model = GPT2LMHeadModel(GPT2Config())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_critic.py
deleted file mode 100644
index 25bb1ed94..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_critic.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers.models.gpt2.configuration_gpt2 import GPT2Config
-from transformers.models.gpt2.modeling_gpt2 import GPT2Model
-
-from ..base import Critic
-
-
-class GPTCritic(Critic):
- """
- GPT Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (GPT2Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the LO-RA decomposition.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[GPT2Config] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = GPT2Model.from_pretrained(pretrained)
- elif config is not None:
- model = GPT2Model(config)
- else:
- model = GPT2Model(GPT2Config())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.n_embd, 1)
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_lm.py
deleted file mode 100644
index c558d7e9e..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_lm.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-from transformers.models.gpt2.configuration_gpt2 import GPT2Config
-from transformers.models.gpt2.modeling_gpt2 import GPT2LMHeadModel
-
-from ..base import LM
-
-
-class GPTLM(LM):
- """
- GPT language model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (GPT2Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the LoRa layer.
- lora_train_bias (str): Bias training strategy for the LoRa layer.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[GPT2Config] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = GPT2LMHeadModel.from_pretrained(pretrained)
- elif config is not None:
- model = GPT2LMHeadModel(config)
- else:
- model = GPT2LMHeadModel(GPT2Config())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
-
- def forward(self, input_ids, attention_mask=None, labels=None, **kwargs):
- return self.model(input_ids, attention_mask=attention_mask, labels=labels, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_rm.py
deleted file mode 100644
index 054432e1c..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/gpt/gpt_rm.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers.models.gpt2.configuration_gpt2 import GPT2Config
-from transformers.models.gpt2.modeling_gpt2 import GPT2Model
-
-from ..base import RewardModel
-
-
-class GPTRM(RewardModel):
- """
- GPT Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (GPT2Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[GPT2Config] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = GPT2Model.from_pretrained(pretrained)
- elif config is not None:
- model = GPT2Model(config)
- else:
- model = GPT2Model(GPT2Config())
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- value_head = nn.Linear(model.config.n_embd, 1)
- value_head.weight.data.normal_(mean=0.0, std=1 / (model.config.n_embd + 1))
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/__init__.py
deleted file mode 100644
index 0d4dada3c..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .llama_actor import LlamaActor
-from .llama_critic import LlamaCritic
-from .llama_lm import LlamaLM
-from .llama_rm import LlamaRM
-
-__all__ = ['LlamaActor', 'LlamaCritic', 'LlamaRM', 'LlamaLM']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_actor.py
deleted file mode 100644
index 2c7adb390..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_actor.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-import torch
-from transformers import AutoModelForCausalLM, LlamaConfig, LlamaForCausalLM
-
-from ..base import Actor
-
-
-class LlamaActor(Actor):
- """
- Llama Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (LlamaConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[LlamaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
-
- if pretrained is not None:
- model = LlamaForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = LlamaForCausalLM(config)
- else:
- model = LlamaForCausalLM(LlamaConfig())
-
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- super().__init__(model, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_critic.py
deleted file mode 100644
index cd565031e..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_critic.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-from transformers import AutoModelForCausalLM, LlamaConfig, LlamaForCausalLM
-
-from ..base import Critic
-
-
-class LlamaCritic(Critic):
- """
- Llama Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (LlamaConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[LlamaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- **kwargs) -> None:
-
- if pretrained is not None:
- model = LlamaForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = LlamaForCausalLM(config)
- else:
- model = LlamaForCausalLM(LlamaConfig())
-
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- value_head = nn.Linear(model.config.hidden_size, 1)
-
- super().__init__(model, value_head, lora_rank, lora_train_bias, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_lm.py
deleted file mode 100644
index 181910fb1..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_lm.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from typing import Optional
-
-from transformers import LlamaConfig, LlamaForCausalLM
-
-from ..base import LM
-
-
-class LlamaLM(LM):
- """
- Llama language model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (LlamaConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[LlamaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
-
- if pretrained is not None:
- model = LlamaForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = LlamaForCausalLM(config)
- else:
- model = LlamaForCausalLM(LlamaConfig())
-
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- super().__init__(model, lora_rank, lora_train_bias)
-
- def forward(self, input_ids, attention_mask=None, labels=None, **kwargs):
- return self.model(input_ids, attention_mask=attention_mask, labels=labels, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_rm.py
deleted file mode 100644
index f936019d6..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/llama/llama_rm.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import LlamaConfig, LlamaForCausalLM, LlamaModel
-
-from ..base import RewardModel
-
-
-class LlamaRM(RewardModel):
- """
- Llama Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (LlamaConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[LlamaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
-
- if pretrained is not None:
- model = LlamaModel.from_pretrained(pretrained)
- elif config is not None:
- model = LlamaModel(config)
- else:
- model = LlamaModel(LlamaConfig())
-
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.hidden_size, 1)
- value_head.weight.data.normal_(mean=0.0, std=1 / (model.config.hidden_size + 1))
-
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/lora.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/lora.py
deleted file mode 100644
index f8f7a1cb5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/lora.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import math
-from typing import Optional
-
-import loralib as lora
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-
-class LoraLinear(lora.LoRALayer, nn.Module):
- """Replace in-place ops to out-of-place ops to fit gemini. Convert a torch.nn.Linear to LoraLinear.
- """
-
- def __init__(
- self,
- weight: nn.Parameter,
- bias: Optional[nn.Parameter],
- r: int = 0,
- lora_alpha: int = 1,
- lora_dropout: float = 0.,
- fan_in_fan_out: bool = False, # Set this to True if the layer to replace stores weight like (fan_in, fan_out)
- merge_weights: bool = True,
- ):
- nn.Module.__init__(self)
- lora.LoRALayer.__init__(self,
- r=r,
- lora_alpha=lora_alpha,
- lora_dropout=lora_dropout,
- merge_weights=merge_weights)
- self.weight = weight
- self.bias = bias
-
- out_features, in_features = weight.shape
- self.in_features = in_features
- self.out_features = out_features
-
- self.fan_in_fan_out = fan_in_fan_out
- # Actual trainable parameters
- if r > 0:
- self.lora_A = nn.Parameter(self.weight.new_zeros((r, in_features)))
- self.lora_B = nn.Parameter(self.weight.new_zeros((out_features, r)))
- self.scaling = self.lora_alpha / self.r
- # Freezing the pre-trained weight matrix
- self.weight.requires_grad = False
- self.reset_parameters()
- if fan_in_fan_out:
- self.weight.data = self.weight.data.T
-
- def reset_parameters(self):
- if hasattr(self, 'lora_A'):
- # initialize A the same way as the default for nn.Linear and B to zero
- nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
- nn.init.zeros_(self.lora_B)
-
- def train(self, mode: bool = True):
-
- def T(w):
- return w.T if self.fan_in_fan_out else w
-
- nn.Module.train(self, mode)
- if self.merge_weights and self.merged:
- # Make sure that the weights are not merged
- if self.r > 0:
- self.weight.data -= T(self.lora_B @ self.lora_A) * self.scaling
- self.merged = False
-
- def eval(self):
-
- def T(w):
- return w.T if self.fan_in_fan_out else w
-
- nn.Module.eval(self)
- if self.merge_weights and not self.merged:
- # Merge the weights and mark it
- if self.r > 0:
- self.weight.data += T(self.lora_B @ self.lora_A) * self.scaling
- delattr(self, 'lora_A')
- delattr(self, 'lora_B')
- self.merged = True
-
- def forward(self, x: torch.Tensor):
-
- def T(w):
- return w.T if self.fan_in_fan_out else w
-
- if self.r > 0 and not self.merged:
- result = F.linear(x, T(self.weight), bias=self.bias)
- if self.r > 0:
- result = result + (self.lora_dropout(x) @ self.lora_A.t() @ self.lora_B.t()) * self.scaling
- return result
- else:
- return F.linear(x, T(self.weight), bias=self.bias)
-
-
-def lora_linear_wrapper(linear: nn.Linear, lora_rank: int) -> LoraLinear:
- assert lora_rank <= linear.in_features, f'LoRA rank ({lora_rank}) must be less than or equal to in features ({linear.in_features})'
- lora_linear = LoraLinear(linear.weight, linear.bias, r=lora_rank, merge_weights=False)
- return lora_linear
-
-
-def convert_to_lora_recursively(module: nn.Module, lora_rank: int) -> None:
- for name, child in module.named_children():
- if isinstance(child, nn.Linear):
- setattr(module, name, lora_linear_wrapper(child, lora_rank))
- else:
- convert_to_lora_recursively(child, lora_rank)
-
-
-class LoRAModule(nn.Module):
- """A LoRA module base class. All derived classes should call `convert_to_lora()` at the bottom of `__init__()`.
- This calss will convert all torch.nn.Linear layer to LoraLinear layer.
-
- Args:
- lora_rank (int, optional): LoRA rank. 0 means LoRA is not applied. Defaults to 0.
- lora_train_bias (str, optional): Whether LoRA train biases.
- 'none' means it doesn't train biases. 'all' means it trains all biases. 'lora_only' means it only trains biases of LoRA layers.
- Defaults to 'none'.
- """
-
- def __init__(self, lora_rank: int = 0, lora_train_bias: str = 'none') -> None:
- super().__init__()
- self.lora_rank = lora_rank
- self.lora_train_bias = lora_train_bias
-
- def convert_to_lora(self) -> None:
- if self.lora_rank <= 0:
- return
- convert_to_lora_recursively(self, self.lora_rank)
- lora.mark_only_lora_as_trainable(self, self.lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/loss.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/loss.py
deleted file mode 100644
index 7fc437d90..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/loss.py
+++ /dev/null
@@ -1,117 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-
-from .utils import masked_mean
-
-
-class GPTLMLoss(nn.Module):
- """
- GPT Language Model Loss
- """
-
- def __init__(self):
- super().__init__()
- self.loss = nn.CrossEntropyLoss()
-
- def forward(self, logits: torch.Tensor, labels: torch.Tensor) -> torch.Tensor:
- shift_logits = logits[..., :-1, :].contiguous()
- shift_labels = labels[..., 1:].contiguous()
- # Flatten the tokens
- return self.loss(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
-
-
-class PolicyLoss(nn.Module):
- """
- Policy Loss for PPO
- """
-
- def __init__(self, clip_eps: float = 0.2) -> None:
- super().__init__()
- self.clip_eps = clip_eps
-
- def forward(self,
- log_probs: torch.Tensor,
- old_log_probs: torch.Tensor,
- advantages: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- ratio = (log_probs - old_log_probs).exp()
- surr1 = ratio * advantages
- surr2 = ratio.clamp(1 - self.clip_eps, 1 + self.clip_eps) * advantages
- loss = -torch.min(surr1, surr2)
- if action_mask is not None:
- loss = masked_mean(loss, action_mask)
- loss = loss.mean()
- return loss
-
-
-class ValueLoss(nn.Module):
- """
- Value Loss for PPO
- """
-
- def __init__(self, clip_eps: float = 0.4) -> None:
- super().__init__()
- self.clip_eps = clip_eps
-
- def forward(self,
- values: torch.Tensor,
- old_values: torch.Tensor,
- reward: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- values_clipped = old_values + (values - old_values).clamp(-self.clip_eps, self.clip_eps)
- surr1 = (values_clipped - reward)**2
- surr2 = (values - reward)**2
- loss = torch.max(surr1, surr2)
- loss = loss.mean()
- return loss
-
-
-class PPOPtxActorLoss(nn.Module):
- """
- To Do:
-
- PPO-ptx Actor Loss
- """
-
- def __init__(self, policy_clip_eps: float = 0.2, pretrain_coef: float = 0.0, pretrain_loss_fn=GPTLMLoss()) -> None:
- super().__init__()
- self.pretrain_coef = pretrain_coef
- self.policy_loss_fn = PolicyLoss(clip_eps=policy_clip_eps)
- self.pretrain_loss_fn = pretrain_loss_fn
-
- def forward(self,
- log_probs: torch.Tensor,
- old_log_probs: torch.Tensor,
- advantages: torch.Tensor,
- lm_logits: torch.Tensor,
- lm_input_ids: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- policy_loss = self.policy_loss_fn(log_probs, old_log_probs, advantages, action_mask=action_mask)
- lm_loss = self.pretrain_loss_fn(lm_logits, lm_input_ids)
- return policy_loss + self.pretrain_coef * lm_loss
-
-
-class LogSigLoss(nn.Module):
- """
- Pairwise Loss for Reward Model
- Details: https://arxiv.org/abs/2203.02155
- """
-
- def forward(self, chosen_reward: torch.Tensor, reject_reward: torch.Tensor) -> torch.Tensor:
- probs = torch.sigmoid(chosen_reward - reject_reward)
- log_probs = torch.log(probs)
- loss = -log_probs.mean()
- return loss
-
-
-class LogExpLoss(nn.Module):
- """
- Pairwise Loss for Reward Model
- Details: https://arxiv.org/abs/2204.05862
- """
-
- def forward(self, chosen_reward: torch.Tensor, reject_reward: torch.Tensor) -> torch.Tensor:
- loss = torch.log(1 + torch.exp(reject_reward - chosen_reward)).mean()
- return loss
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/__init__.py
deleted file mode 100644
index 3d7a8adbf..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .opt_actor import OPTActor
-from .opt_critic import OPTCritic
-from .opt_lm import OPTLM
-from .opt_rm import OPTRM
-
-__all__ = ['OPTActor', 'OPTCritic', 'OPTRM', 'OPTLM']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_actor.py
deleted file mode 100644
index c14e4377f..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_actor.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Optional
-
-from transformers.models.opt.configuration_opt import OPTConfig
-from transformers.models.opt.modeling_opt import OPTForCausalLM
-
-from ..base import Actor
-
-
-class OPTActor(Actor):
- """
- OPT Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (OPTConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[OPTConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = OPTForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = OPTForCausalLM(config)
- else:
- model = OPTForCausalLM(OPTConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_critic.py
deleted file mode 100644
index fcfebd8a8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_critic.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers.models.opt.configuration_opt import OPTConfig
-from transformers.models.opt.modeling_opt import OPTModel
-
-from ..base import Critic
-
-
-class OPTCritic(Critic):
- """
- OPT Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (OPTConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[OPTConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- **kwargs) -> None:
- if pretrained is not None:
- model = OPTModel.from_pretrained(pretrained)
- elif config is not None:
- model = OPTModel(config)
- else:
- model = OPTModel(OPTConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.word_embed_proj_dim, 1)
- super().__init__(model, value_head, lora_rank, lora_train_bias, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_lm.py
deleted file mode 100644
index 47afae847..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_lm.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-from transformers.models.opt.configuration_opt import OPTConfig
-from transformers.models.opt.modeling_opt import OPTForCausalLM
-
-from ..base import LM
-
-
-class OPTLM(LM):
- """
- OPT language model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (OPTConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[OPTConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = OPTForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = OPTForCausalLM(config)
- else:
- model = OPTForCausalLM(OPTConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
-
- def forward(self, input_ids, attention_mask=None, labels=None, **kwargs):
- return self.model(input_ids, attention_mask=attention_mask, labels=labels, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_rm.py
deleted file mode 100644
index 50fc0dee8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/opt/opt_rm.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import OPTConfig, OPTModel
-
-from ..base import RewardModel
-
-
-class OPTRM(RewardModel):
- """
- OPT Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (OPTConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[OPTConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = OPTModel.from_pretrained(pretrained)
- elif config is not None:
- model = OPTModel(config)
- else:
- model = OPTModel(OPTConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- value_head = nn.Linear(model.config.word_embed_proj_dim, 1)
- value_head.weight.data.normal_(mean=0.0, std=1 / (model.config.word_embed_proj_dim + 1))
- super().__init__(model, value_head, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/__init__.py
deleted file mode 100644
index 0f4a8de06..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .roberta_actor import RoBERTaActor
-from .roberta_critic import RoBERTaCritic
-from .roberta_rm import RoBERTaRM
-
-__all__ = ['RoBERTaActor', 'RoBERTaCritic', 'RoBERTaRM']
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_actor.py
deleted file mode 100644
index e35fa6eb1..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_actor.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Optional
-
-from transformers.models.roberta.configuration_roberta import RobertaConfig
-from transformers.models.roberta.modeling_roberta import RobertaForCausalLM
-
-from ..base import Actor
-
-class RoBERTaActor(Actor):
- """
- RoBERTa Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (RoBERTaConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[RobertaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = RobertaForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = RobertaForCausalLM(config)
- else:
- model = RobertaForCausalLM(RobertaConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_critic.py
deleted file mode 100644
index c8dc0d9e1..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_critic.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers.models.roberta.configuration_roberta import RobertaConfig
-from transformers.models.roberta.modeling_roberta import RobertaModel
-
-from ..base import Critic
-
-
-class RoBERTaCritic(Critic):
- """
- RoBERTa Critic model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (RoBERTa Config): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[RobertaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- **kwargs) -> None:
- if pretrained is not None:
- model = RobertaModel.from_pretrained(pretrained, add_pooling_layer=False)
- elif config is not None:
- model = RobertaModel(config)
- else:
- model = RobertaModel(RobertaConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- value_head = nn.Linear(model.config.hidden_size, 1)
- super().__init__(model, value_head, lora_rank, lora_train_bias, **kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_rm.py
deleted file mode 100644
index 770750529..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/roberta/roberta_rm.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from typing import Optional
-
-import torch.nn as nn
-from transformers import RobertaConfig, RobertaModel
-
-
-from ..base import RewardModel
-
-
-class RoBERTaRM(RewardModel):
- """
- RoBERTa Reward model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (RoBERTaConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[RobertaConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = RobertaModel.from_pretrained(pretrained, add_pooling_layer=False)
- elif config is not None:
- model = RobertaModel(config)
- else:
- model = RobertaModel(RobertaConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
-
- value_head = nn.Linear(model.config.hidden_size, 1)
- value_head.weight.data.normal_(mean=0.0, std=1/(model.config.hidden_size + 1))
- super().__init__(model, value_head, lora_rank, lora_train_bias)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/utils.py
deleted file mode 100644
index 0ff13181f..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/models/utils.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from typing import Optional, Union
-
-import loralib as lora
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-
-def compute_approx_kl(log_probs: torch.Tensor,
- log_probs_base: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- """
- Compute the approximate KL divergence between two distributions.
- Schulman blog: http://joschu.net/blog/kl-approx.html
-
- Args:
- log_probs: Log probabilities of the new distribution.
- log_probs_base: Log probabilities of the base distribution.
- action_mask: Mask for actions.
- """
-
- log_ratio = log_probs - log_probs_base
- approx_kl = (log_ratio.exp() - 1) - log_ratio
- if action_mask is not None:
- approx_kl = masked_mean(approx_kl, action_mask, dim=1)
- return approx_kl
- approx_kl = approx_kl.mean(dim=1)
- return approx_kl
-
-
-def compute_reward(r: Union[torch.Tensor, float],
- kl_coef: float,
- log_probs: torch.Tensor,
- log_probs_base: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- if kl_coef <= 0.0:
- return r
- kl = compute_approx_kl(log_probs, log_probs_base, action_mask=action_mask)
- reward = r - kl_coef * kl
- return reward
-
-
-def log_probs_from_logits(logits: torch.Tensor, labels: torch.Tensor) -> torch.Tensor:
- log_probs = F.log_softmax(logits, dim=-1)
- log_probs_labels = log_probs.gather(dim=-1, index=labels.unsqueeze(-1))
- return log_probs_labels.squeeze(-1)
-
-
-def masked_mean(tensor: torch.Tensor, mask: torch.Tensor, dim: int = 1) -> torch.Tensor:
- tensor = tensor * mask
- tensor = tensor.sum(dim=dim)
- mask_sum = mask.sum(dim=dim)
- mean = tensor / (mask_sum + 1e-8)
- return mean
-
-
-def masked_normalize(tensor: torch.Tensor, mask: torch.Tensor, dim: int = 1, eps: float = 1e-8) -> torch.Tensor:
- tensor = tensor * mask
- mean = masked_mean(tensor, mask, dim=dim)
- mean_centered = tensor - mean
- var = masked_mean(mean_centered**2, mask, dim=dim)
- return mean_centered * var.clamp(min=eps).rsqrt()
-
-
-def normalize(tensor: torch.Tensor, dim: int = 0, eps: float = 1e-8) -> torch.Tensor:
- mean = tensor.mean(dim)
- mean_centered = tensor - mean
- var = (mean_centered**2).mean(dim)
- norm = mean_centered * var.clamp(min=eps).rsqrt()
- return norm
-
-
-def convert_to_lora(model: nn.Module,
- input_size: int,
- output_size: int,
- lora_rank: int = 16,
- lora_alpha: int = 1,
- lora_dropout: float = 0.,
- fan_in_fan_out: bool = False,
- merge_weights: bool = True):
- if lora_rank > min(input_size, output_size):
- raise ValueError(f"LoRA rank {lora_rank} must be less or equal than {min(input_size, output_size)}")
-
- for name, module in model.named_modules():
- if isinstance(module, nn.Linear):
- module._modules[name] = lora.Linear(input_size,
- output_size,
- r=lora_rank,
- lora_alpha=lora_alpha,
- lora_dropout=lora_dropout,
- fan_in_fan_out=fan_in_fan_out,
- merge_weights=merge_weights)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/__init__.py
deleted file mode 100644
index 1ebf60382..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .base import ReplayBuffer
-from .naive import NaiveReplayBuffer
-
-__all__ = ['ReplayBuffer', 'NaiveReplayBuffer']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/base.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/base.py
deleted file mode 100644
index 4c3812461..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/base.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from abc import ABC, abstractmethod
-from typing import Any
-
-from coati.experience_maker.base import Experience
-
-
-class ReplayBuffer(ABC):
- """Replay buffer base class. It stores experience.
-
- Args:
- sample_batch_size (int): Batch size when sampling.
- limit (int, optional): Limit of number of experience samples. A number <= 0 means unlimited. Defaults to 0.
- """
-
- def __init__(self, sample_batch_size: int, limit: int = 0) -> None:
- super().__init__()
- self.sample_batch_size = sample_batch_size
- # limit <= 0 means unlimited
- self.limit = limit
-
- @abstractmethod
- def append(self, experience: Experience) -> None:
- pass
-
- @abstractmethod
- def clear(self) -> None:
- pass
-
- @abstractmethod
- def sample(self) -> Experience:
- pass
-
- @abstractmethod
- def __len__(self) -> int:
- pass
-
- @abstractmethod
- def __getitem__(self, idx: int) -> Any:
- pass
-
- @abstractmethod
- def collate_fn(self, batch: Any) -> Experience:
- pass
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/naive.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/naive.py
deleted file mode 100644
index 938f50064..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/naive.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import random
-from typing import List
-
-import torch
-from coati.experience_maker.base import Experience
-
-from .base import ReplayBuffer
-from .utils import BufferItem, make_experience_batch, split_experience_batch
-
-
-class NaiveReplayBuffer(ReplayBuffer):
- """Naive replay buffer class. It stores experience.
-
- Args:
- sample_batch_size (int): Batch size when sampling.
- limit (int, optional): Limit of number of experience samples. A number <= 0 means unlimited. Defaults to 0.
- cpu_offload (bool, optional): Whether to offload experience to cpu when sampling. Defaults to True.
- """
-
- def __init__(self, sample_batch_size: int, limit: int = 0, cpu_offload: bool = True) -> None:
- super().__init__(sample_batch_size, limit)
- self.cpu_offload = cpu_offload
- self.target_device = torch.device(f'cuda:{torch.cuda.current_device()}')
- # TODO(ver217): add prefetch
- self.items: List[BufferItem] = []
-
- @torch.no_grad()
- def append(self, experience: Experience) -> None:
- if self.cpu_offload:
- experience.to_device(torch.device('cpu'))
- items = split_experience_batch(experience)
- self.items.extend(items)
- if self.limit > 0:
- samples_to_remove = len(self.items) - self.limit
- if samples_to_remove > 0:
- self.items = self.items[samples_to_remove:]
-
- def clear(self) -> None:
- self.items.clear()
-
- @torch.no_grad()
- def sample(self) -> Experience:
- items = random.sample(self.items, self.sample_batch_size)
- experience = make_experience_batch(items)
- if self.cpu_offload:
- experience.to_device(self.target_device)
- return experience
-
- def __len__(self) -> int:
- return len(self.items)
-
- def __getitem__(self, idx: int) -> BufferItem:
- return self.items[idx]
-
- def collate_fn(self, batch) -> Experience:
- experience = make_experience_batch(batch)
- return experience
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/utils.py
deleted file mode 100644
index 55ddb2ae8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/replay_buffer/utils.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from dataclasses import dataclass
-from typing import List, Optional
-
-import torch
-import torch.nn.functional as F
-from coati.experience_maker.base import Experience
-
-
-@dataclass
-class BufferItem:
- """BufferItem is an item of experience data.
-
- Shapes of each tensor:
- sequences: (S)
- action_log_probs: (A)
- values: (1)
- reward: (1)
- advatanges: (1)
- attention_mask: (S)
- action_mask: (A)
-
- "A" is the number of actions.
- """
- sequences: torch.Tensor
- action_log_probs: torch.Tensor
- values: torch.Tensor
- reward: torch.Tensor
- advantages: torch.Tensor
- attention_mask: Optional[torch.LongTensor]
- action_mask: Optional[torch.BoolTensor]
-
-
-def split_experience_batch(experience: Experience) -> List[BufferItem]:
- batch_size = experience.sequences.size(0)
- batch_kwargs = [{} for _ in range(batch_size)]
- keys = ('sequences', 'action_log_probs', 'values', 'reward', 'advantages', 'attention_mask', 'action_mask')
- for key in keys:
- value = getattr(experience, key)
- if isinstance(value, torch.Tensor):
- vals = torch.unbind(value)
- else:
- # None
- vals = [value for _ in range(batch_size)]
- assert batch_size == len(vals)
- for i, v in enumerate(vals):
- batch_kwargs[i][key] = v
- items = [BufferItem(**kwargs) for kwargs in batch_kwargs]
- return items
-
-
-def zero_pad_sequences(sequences: List[torch.Tensor], side: str = 'left') -> torch.Tensor:
- assert side in ('left', 'right')
- max_len = max(seq.size(0) for seq in sequences)
- padded_sequences = []
- for seq in sequences:
- pad_len = max_len - seq.size(0)
- padding = (pad_len, 0) if side == 'left' else (0, pad_len)
- padded_sequences.append(F.pad(seq, padding))
- return torch.stack(padded_sequences, dim=0)
-
-
-def make_experience_batch(items: List[BufferItem]) -> Experience:
- kwargs = {}
- to_pad_keys = set(('action_log_probs', 'action_mask'))
- keys = ('sequences', 'action_log_probs', 'values', 'reward', 'advantages', 'attention_mask', 'action_mask')
- for key in keys:
- vals = [getattr(item, key) for item in items]
- if key in to_pad_keys:
- batch_data = zero_pad_sequences(vals)
- else:
- batch_data = torch.stack(vals, dim=0)
- kwargs[key] = batch_data
- return Experience(**kwargs)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/__init__.py
deleted file mode 100644
index 525b57bf2..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .base import Trainer
-from .ppo import PPOTrainer
-from .rm import RewardModelTrainer
-from .sft import SFTTrainer
-
-__all__ = ['Trainer', 'PPOTrainer', 'RewardModelTrainer', 'SFTTrainer']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/base.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/base.py
deleted file mode 100644
index 610bb5111..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/base.py
+++ /dev/null
@@ -1,168 +0,0 @@
-from abc import ABC, abstractmethod
-from typing import Any, Callable, Dict, List, Optional, Union
-
-import torch
-from coati.experience_maker import Experience, ExperienceMaker
-from coati.replay_buffer import ReplayBuffer
-from torch import Tensor
-from torch.utils.data import DistributedSampler
-from tqdm import tqdm
-
-from .callbacks import Callback
-from .strategies import Strategy
-from .utils import is_rank_0
-
-
-class Trainer(ABC):
- """
- Base class for rlhf trainers.
-
- Args:
- strategy (Strategy):the strategy to use for training
- experience_maker (ExperienceMaker): the experience maker to use for produce experience to fullfill replay buffer
- replay_buffer (ReplayBuffer): the replay buffer to use for training
- experience_batch_size (int, defaults to 8): the batch size to use for experience generation
- max_epochs (int, defaults to 1): the number of epochs of training process
- tokenizer (Callable, optional): the tokenizer to use for tokenizing the input
- sample_replay_buffer (bool, defaults to False): whether to sample from replay buffer
- data_loader_pin_memory (bool, defaults to True): whether to pin memory for data loader
- callbacks (List[Callback], defaults to []): the callbacks to call during training process
- generate_kwargs (dict, optional): the kwargs to use while model generating
- """
-
- def __init__(self,
- strategy: Strategy,
- experience_maker: ExperienceMaker,
- replay_buffer: ReplayBuffer,
- experience_batch_size: int = 8,
- max_epochs: int = 1,
- tokenizer: Optional[Callable[[Any], dict]] = None,
- sample_replay_buffer: bool = False,
- dataloader_pin_memory: bool = True,
- callbacks: List[Callback] = [],
- **generate_kwargs) -> None:
- super().__init__()
- self.strategy = strategy
- self.experience_maker = experience_maker
- self.replay_buffer = replay_buffer
- self.experience_batch_size = experience_batch_size
- self.max_epochs = max_epochs
- self.tokenizer = tokenizer
- self.generate_kwargs = generate_kwargs
- self.sample_replay_buffer = sample_replay_buffer
- self.dataloader_pin_memory = dataloader_pin_memory
- self.callbacks = callbacks
-
- @abstractmethod
- def training_step(self, experience: Experience) -> Dict[str, Any]:
- pass
-
- def _make_experience(self, inputs: Union[Tensor, Dict[str, Tensor]]) -> Experience:
- if isinstance(inputs, Tensor):
- return self.experience_maker.make_experience(inputs, **self.generate_kwargs)
- elif isinstance(inputs, dict):
- return self.experience_maker.make_experience(**inputs, **self.generate_kwargs)
- else:
- raise ValueError(f'Unsupported input type "{type(inputs)}"')
-
- def _sample_prompts(self, prompts) -> list:
- indices = list(range(len(prompts)))
- sampled_indices = self.strategy.experience_sampler.choice(indices, self.experience_batch_size, replace=False)
- return [prompts[i] for i in sampled_indices]
-
- def _learn(self):
- # replay buffer may be empty at first, we should rebuild at each training
- if not self.sample_replay_buffer:
- dataloader = self.strategy.setup_dataloader(self.replay_buffer, self.dataloader_pin_memory)
- device = torch.cuda.current_device()
- if self.sample_replay_buffer:
- pbar = tqdm(range(self.max_epochs), desc='Train epoch', disable=not is_rank_0())
- for _ in pbar:
- experience = self.replay_buffer.sample()
- metrics = self.training_step(experience)
- pbar.set_postfix(metrics)
- else:
- for epoch in range(self.max_epochs):
- self._on_learn_epoch_start(epoch)
- if isinstance(dataloader.sampler, DistributedSampler):
- dataloader.sampler.set_epoch(epoch)
- pbar = tqdm(dataloader, desc=f'Train epoch [{epoch+1}/{self.max_epochs}]', disable=not is_rank_0())
- for experience in pbar:
- self._on_learn_batch_start()
- experience.to_device(device)
- metrics = self.training_step(experience)
- self._on_learn_batch_end(metrics, experience)
- pbar.set_postfix(metrics)
- self._on_learn_epoch_end(epoch)
-
- def fit(self,
- prompt_dataloader,
- pretrain_dataloader,
- num_episodes: int = 50000,
- max_timesteps: int = 500,
- update_timesteps: int = 5000) -> None:
- time = 0
- self.pretrain_dataloader = pretrain_dataloader
- self.prompt_dataloader = prompt_dataloader
- self._on_fit_start()
- for episode in range(num_episodes):
- self._on_episode_start(episode)
- for timestep in tqdm(range(max_timesteps),
- desc=f'Episode [{episode+1}/{num_episodes}]',
- disable=not is_rank_0()):
- time += 1
- prompts = next(iter(self.prompt_dataloader))
- self._on_make_experience_start()
- self.experience_maker.initial_model.to(torch.cuda.current_device())
- self.experience_maker.reward_model.to(torch.cuda.current_device())
- experience = self._make_experience(prompts)
- self._on_make_experience_end(experience)
- self.replay_buffer.append(experience)
- if time % update_timesteps == 0:
- self.experience_maker.initial_model.to('cpu')
- self.experience_maker.reward_model.to('cpu')
- self._learn()
- self.replay_buffer.clear()
- self._on_episode_end(episode)
- self._on_fit_end()
-
- # TODO(ver217): maybe simplify these code using context
- def _on_fit_start(self) -> None:
- for callback in self.callbacks:
- callback.on_fit_start()
-
- def _on_fit_end(self) -> None:
- for callback in self.callbacks:
- callback.on_fit_end()
-
- def _on_episode_start(self, episode: int) -> None:
- for callback in self.callbacks:
- callback.on_episode_start(episode)
-
- def _on_episode_end(self, episode: int) -> None:
- for callback in self.callbacks:
- callback.on_episode_end(episode)
-
- def _on_make_experience_start(self) -> None:
- for callback in self.callbacks:
- callback.on_make_experience_start()
-
- def _on_make_experience_end(self, experience: Experience) -> None:
- for callback in self.callbacks:
- callback.on_make_experience_end(experience)
-
- def _on_learn_epoch_start(self, epoch: int) -> None:
- for callback in self.callbacks:
- callback.on_learn_epoch_start(epoch)
-
- def _on_learn_epoch_end(self, epoch: int) -> None:
- for callback in self.callbacks:
- callback.on_learn_epoch_end(epoch)
-
- def _on_learn_batch_start(self) -> None:
- for callback in self.callbacks:
- callback.on_learn_batch_start()
-
- def _on_learn_batch_end(self, metrics: dict, experience: Experience) -> None:
- for callback in self.callbacks:
- callback.on_learn_batch_end(metrics, experience)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/__init__.py
deleted file mode 100644
index 9ed0ee6f7..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .base import Callback
-from .performance_evaluator import PerformanceEvaluator
-from .save_checkpoint import SaveCheckpoint
-
-__all__ = ['Callback', 'PerformanceEvaluator', 'SaveCheckpoint']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/base.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/base.py
deleted file mode 100644
index f56160488..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/base.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from abc import ABC
-
-from coati.experience_maker import Experience
-
-
-class Callback(ABC):
- """
- Base callback class. It defines the interface for callbacks.
- """
-
- def on_fit_start(self) -> None:
- pass
-
- def on_fit_end(self) -> None:
- pass
-
- def on_episode_start(self, episode: int) -> None:
- pass
-
- def on_episode_end(self, episode: int) -> None:
- pass
-
- def on_make_experience_start(self) -> None:
- pass
-
- def on_make_experience_end(self, experience: Experience) -> None:
- pass
-
- def on_learn_epoch_start(self, epoch: int) -> None:
- pass
-
- def on_learn_epoch_end(self, epoch: int) -> None:
- pass
-
- def on_learn_batch_start(self) -> None:
- pass
-
- def on_learn_batch_end(self, metrics: dict, experience: Experience) -> None:
- pass
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/performance_evaluator.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/performance_evaluator.py
deleted file mode 100644
index 0fc3b077a..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/performance_evaluator.py
+++ /dev/null
@@ -1,133 +0,0 @@
-from time import time
-from typing import Optional
-
-import torch
-import torch.distributed as dist
-from coati.experience_maker import Experience
-
-from .base import Callback
-
-
-def get_world_size() -> int:
- if dist.is_initialized():
- return dist.get_world_size()
- return 1
-
-
-def print_rank_0(*args, **kwargs) -> None:
- if not dist.is_initialized() or dist.get_rank() == 0:
- print(*args, **kwargs)
-
-
-@torch.no_grad()
-def all_reduce_mean(x: float, world_size: int) -> float:
- if world_size == 1:
- return x
- tensor = torch.tensor([x], device=torch.cuda.current_device())
- dist.all_reduce(tensor)
- tensor = tensor / world_size
- return tensor.item()
-
-
-class PerformanceEvaluator(Callback):
- """
- Callback for valuate the performance of the model.
- Args:
- actor_num_params: The number of parameters of the actor model.
- critic_num_params: The number of parameters of the critic model.
- initial_model_num_params: The number of parameters of the initial model.
- reward_model_num_params: The number of parameters of the reward model.
- enable_grad_checkpoint: Whether to enable gradient checkpointing.
- ignore_episodes: The number of episodes to ignore when calculating the performance.
- """
-
- def __init__(self,
- actor_num_params: int,
- critic_num_params: int,
- initial_model_num_params: int,
- reward_model_num_params: int,
- enable_grad_checkpoint: bool = False,
- ignore_episodes: int = 0) -> None:
- super().__init__()
- self.world_size = get_world_size()
- self.actor_num_params = actor_num_params
- self.critic_num_params = critic_num_params
- self.initial_model_num_params = initial_model_num_params
- self.reward_model_num_params = reward_model_num_params
- self.enable_grad_checkpoint = enable_grad_checkpoint
- self.ignore_episodes = ignore_episodes
- self.disable: bool = False
-
- self.make_experience_duration: float = 0.
- self.make_experience_start_time: Optional[float] = None
- self.make_experience_num_samples: int = 0
- self.make_experience_flop: int = 0
- self.learn_duration: float = 0.
- self.learn_start_time: Optional[float] = None
- self.learn_num_samples: int = 0
- self.learn_flop: int = 0
-
- def on_episode_start(self, episode: int) -> None:
- self.disable = self.ignore_episodes > 0 and episode < self.ignore_episodes
-
- def on_make_experience_start(self) -> None:
- if self.disable:
- return
- self.make_experience_start_time = time()
-
- def on_make_experience_end(self, experience: Experience) -> None:
- if self.disable:
- return
- self.make_experience_duration += time() - self.make_experience_start_time
-
- batch_size, seq_len = experience.sequences.shape
-
- self.make_experience_num_samples += batch_size
-
- # actor generate
- num_actions = experience.action_mask.size(1)
- input_len = seq_len - num_actions
- total_seq_len = (input_len + seq_len - 1) * num_actions / 2
- self.make_experience_flop += self.actor_num_params * batch_size * total_seq_len * 2
- # actor forward
- self.make_experience_flop += self.actor_num_params * batch_size * seq_len * 2
- # critic forward
- self.make_experience_flop += self.critic_num_params * batch_size * seq_len * 2
- # initial model forward
- self.make_experience_flop += self.initial_model_num_params * batch_size * seq_len * 2
- # reward model forward
- self.make_experience_flop += self.reward_model_num_params * batch_size * seq_len * 2
-
- def on_learn_batch_start(self) -> None:
- if self.disable:
- return
- self.learn_start_time = time()
-
- def on_learn_batch_end(self, metrics: dict, experience: Experience) -> None:
- if self.disable:
- return
- self.learn_duration += time() - self.learn_start_time
-
- batch_size, seq_len = experience.sequences.shape
-
- self.learn_num_samples += batch_size
-
- # actor forward-backward, 3 means forward(1) + backward(2)
- self.learn_flop += self.actor_num_params * batch_size * seq_len * 2 * (3 + int(self.enable_grad_checkpoint))
- # critic foward-backward
- self.learn_flop += self.critic_num_params * batch_size * seq_len * 2 * (3 + int(self.enable_grad_checkpoint))
-
- def on_fit_end(self) -> None:
- avg_make_experience_duration = all_reduce_mean(self.make_experience_duration, self.world_size)
- avg_learn_duration = all_reduce_mean(self.learn_duration, self.world_size)
-
- avg_make_experience_throughput = self.make_experience_num_samples / (avg_make_experience_duration + 1e-12)
- avg_make_experience_tflops = self.make_experience_flop / 1e12 / (avg_make_experience_duration + 1e-12)
-
- avg_learn_throughput = self.learn_num_samples / (avg_learn_duration + 1e-12)
- avg_learn_tflops = self.learn_flop / 1e12 / (avg_learn_duration + 1e-12)
-
- print_rank_0(
- f'Making experience throughput: {avg_make_experience_throughput:.3f} samples/sec, TFLOPS: {avg_make_experience_tflops:.3f}'
- )
- print_rank_0(f'Learning throughput: {avg_learn_throughput:.3f} samples/sec, TFLOPS: {avg_learn_tflops:.3f}')
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/save_checkpoint.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/save_checkpoint.py
deleted file mode 100644
index d2dcc0dd4..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/callbacks/save_checkpoint.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import os
-
-import torch.distributed as dist
-from coati.trainer.strategies import ColossalAIStrategy, Strategy
-from coati.trainer.utils import is_rank_0
-from torch import nn
-from torch.optim import Optimizer
-
-from .base import Callback
-
-
-class SaveCheckpoint(Callback):
- """
- The callback for saving checkpoint for coati.
-
- Only support saving actor and critic model.
- A typical architecture of the saved checkpoint would be:
- - checkpoint
- - episode_x
- - actor.pt
- - actor-optim-rank-0.pt
- - actor-optim-rank-1.pt
- - critic.pt
- - critic-optim-rank-0.pt
- - critic-optim-rank-1.pt
- - ...
-
- Args:
- path(str): the base path you want to save checkpoint, the checkpoint would be saved at `path/checkpoint`
- interval(int): the interval episode of saving checkpoint
- strategy(Strategy): the strategy used to train
- actor(nn.Module): the actor model
- critic(nn.Module): the critic model
- actor_optim(Optimizer): the optimizer of actor
- critic_optim(Optimizer): the optimizer of critic
-
- """
-
- def __init__(self,
- path: str,
- interval: int,
- strategy: Strategy,
- actor: nn.Module = None,
- critic: nn.Module = None,
- actor_optim: Optimizer = None,
- critic_optim: Optimizer = None) -> None:
- super().__init__()
- self.path = os.path.join(path, 'checkpoint')
- self.interval = interval
- self.strategy = strategy
- self.model_dict = {'actor': [actor, actor_optim], 'critic': [critic, critic_optim]}
-
- def on_episode_end(self, episode: int) -> None:
- if (episode + 1) % self.interval != 0:
- return
- base_path = os.path.join(self.path, f'episode_{episode}')
- if not os.path.exists(base_path):
- os.makedirs(base_path)
-
- for model in self.model_dict.keys():
-
- # save model
- if self.model_dict[model][0] is None:
- # saving only optimizer states is meaningless, so it would be skipped
- continue
- model_path = os.path.join(base_path, f'{model}.pt')
- self.strategy.save_model(model=self.model_dict[model][0], path=model_path, only_rank0=True)
-
- # save optimizer
- if self.model_dict[model][1] is None:
- continue
- only_rank0 = not isinstance(self.strategy, ColossalAIStrategy)
- rank = 0 if is_rank_0() else dist.get_rank()
- optim_path = os.path.join(base_path, f'{model}-optim-rank-{rank}.pt')
- self.strategy.save_optimizer(optimizer=self.model_dict[model][1], path=optim_path, only_rank0=only_rank0)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/ppo.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/ppo.py
deleted file mode 100644
index 84254d50d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/ppo.py
+++ /dev/null
@@ -1,135 +0,0 @@
-from typing import Any, Callable, Dict, List, Optional
-
-import torch
-import torch.nn as nn
-from coati.experience_maker import Experience, NaiveExperienceMaker
-from coati.models.base import Actor, Critic
-from coati.models.generation_utils import update_model_kwargs_fn
-from coati.models.loss import PolicyLoss, ValueLoss
-from coati.replay_buffer import NaiveReplayBuffer
-from torch.optim import Optimizer
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .base import Trainer
-from .callbacks import Callback
-from .strategies import Strategy
-
-
-class PPOTrainer(Trainer):
- """
- Trainer for PPO algorithm.
-
- Args:
- strategy (Strategy): the strategy to use for training
- actor (Actor): the actor model in ppo algorithm
- critic (Critic): the critic model in ppo algorithm
- reward_model (nn.Module): the reward model in rlhf algorithm to make reward of sentences
- initial_model (Actor): the initial model in rlhf algorithm to generate reference logits to limit the update of actor
- actor_optim (Optimizer): the optimizer to use for actor model
- critic_optim (Optimizer): the optimizer to use for critic model
- kl_coef (float, defaults to 0.1): the coefficient of kl divergence loss
- train_batch_size (int, defaults to 8): the batch size to use for training
- buffer_limit (int, defaults to 0): the max_size limitaiton of replay buffer
- buffer_cpu_offload (bool, defaults to True): whether to offload replay buffer to cpu
- eps_clip (float, defaults to 0.2): the clip coefficient of policy loss
- value_clip (float, defaults to 0.4): the clip coefficient of value loss
- experience_batch_size (int, defaults to 8): the batch size to use for experience generation
- max_epochs (int, defaults to 1): the number of epochs of training process
- tokenier (Callable, optional): the tokenizer to use for tokenizing the input
- sample_replay_buffer (bool, defaults to False): whether to sample from replay buffer
- dataloader_pin_memory (bool, defaults to True): whether to pin memory for data loader
- callbacks (List[Callback], defaults to []): the callbacks to call during training process
- generate_kwargs (dict, optional): the kwargs to use while model generating
- """
-
- def __init__(self,
- strategy: Strategy,
- actor: Actor,
- critic: Critic,
- reward_model: nn.Module,
- initial_model: Actor,
- actor_optim: Optimizer,
- critic_optim: Optimizer,
- kl_coef: float = 0.1,
- ptx_coef: float = 0.9,
- train_batch_size: int = 8,
- buffer_limit: int = 0,
- buffer_cpu_offload: bool = True,
- eps_clip: float = 0.2,
- value_clip: float = 0.4,
- experience_batch_size: int = 8,
- max_epochs: int = 1,
- tokenizer: Optional[Callable[[Any], dict]] = None,
- sample_replay_buffer: bool = False,
- dataloader_pin_memory: bool = True,
- callbacks: List[Callback] = [],
- **generate_kwargs) -> None:
- experience_maker = NaiveExperienceMaker(actor, critic, reward_model, initial_model, kl_coef)
- replay_buffer = NaiveReplayBuffer(train_batch_size, buffer_limit, buffer_cpu_offload)
- generate_kwargs = _set_default_generate_kwargs(strategy, generate_kwargs, actor)
- super().__init__(strategy, experience_maker, replay_buffer, experience_batch_size, max_epochs, tokenizer,
- sample_replay_buffer, dataloader_pin_memory, callbacks, **generate_kwargs)
- self.actor = actor
- self.critic = critic
-
- self.actor_loss_fn = PolicyLoss(eps_clip)
- self.critic_loss_fn = ValueLoss(value_clip)
- self.ptx_loss_fn = nn.CrossEntropyLoss(ignore_index=-100)
- self.ptx_coef = ptx_coef
- self.actor_optim = actor_optim
- self.critic_optim = critic_optim
-
- def training_step(self, experience: Experience) -> Dict[str, float]:
- self.actor.train()
- self.critic.train()
- # policy loss
- num_actions = experience.action_mask.size(1)
- action_log_probs = self.actor(experience.sequences, num_actions, attention_mask=experience.attention_mask)
- actor_loss = self.actor_loss_fn(action_log_probs,
- experience.action_log_probs,
- experience.advantages,
- action_mask=experience.action_mask)
-
- # ptx loss
- if self.ptx_coef != 0:
- ptx = next(iter(self.pretrain_dataloader))['input_ids'].to(torch.cuda.current_device())
- label = next(iter(self.pretrain_dataloader))['labels'].to(torch.cuda.current_device())[:, 1:]
- attention_mask = next(iter(self.pretrain_dataloader))['attention_mask'].to(torch.cuda.current_device())
- ptx_log_probs = self.actor.get_base_model()(ptx, attention_mask=attention_mask)['logits'][..., :-1, :]
- ptx_loss = self.ptx_loss_fn(ptx_log_probs.view(-1, ptx_log_probs.size(-1)), label.view(-1))
- actor_loss = ptx_loss * self.ptx_coef + actor_loss * (1 - self.ptx_coef)
-
- self.strategy.backward(actor_loss, self.actor, self.actor_optim)
- self.strategy.optimizer_step(self.actor_optim)
- self.actor_optim.zero_grad()
-
- # value loss
- values = self.critic(experience.sequences,
- action_mask=experience.action_mask,
- attention_mask=experience.attention_mask)
- critic_loss = self.critic_loss_fn(values,
- experience.values,
- experience.reward,
- action_mask=experience.action_mask)
- self.strategy.backward(critic_loss, self.critic, self.critic_optim)
- self.strategy.optimizer_step(self.critic_optim)
- self.critic_optim.zero_grad()
-
- return {'reward': experience.reward.mean().item()}
-
-
-def _set_default_generate_kwargs(strategy: Strategy, generate_kwargs: dict, actor: Actor) -> None:
- origin_model = strategy._unwrap_actor(actor)
- new_kwargs = {**generate_kwargs}
- # use huggingface models method directly
- if 'prepare_inputs_fn' not in generate_kwargs and hasattr(origin_model, 'prepare_inputs_for_generation'):
- new_kwargs['prepare_inputs_fn'] = origin_model.prepare_inputs_for_generation
-
- if 'update_model_kwargs_fn' not in generate_kwargs:
- new_kwargs['update_model_kwargs_fn'] = update_model_kwargs_fn
-
- return new_kwargs
-
-
-def save_model(self, path: str, only_rank0: bool = False, tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- self.strategy.save_model(model=self.actor, path=path, only_rank0=only_rank0, tokenizer=tokenizer)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/rm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/rm.py
deleted file mode 100644
index 0cf09b041..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/rm.py
+++ /dev/null
@@ -1,135 +0,0 @@
-from abc import ABC
-from datetime import datetime
-from typing import Optional
-
-import pandas as pd
-import torch
-import torch.distributed as dist
-from torch.optim import Optimizer, lr_scheduler
-from torch.utils.data import DataLoader, Dataset, DistributedSampler
-from tqdm import tqdm
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .strategies import Strategy
-from .utils import is_rank_0
-
-
-class RewardModelTrainer(ABC):
- """
- Trainer to use while training reward model.
-
- Args:
- model (torch.nn.Module): the model to train
- strategy (Strategy): the strategy to use for training
- optim(Optimizer): the optimizer to use for training
- loss_fn (callable): the loss function to use for training
- train_dataset (Dataset): the dataset to use for training
- valid_dataset (Dataset): the dataset to use for validation
- eval_dataset (Dataset): the dataset to use for evaluation
- batch_size (int, defaults to 1): the batch size while training
- max_epochs (int, defaults to 2): the number of epochs to train
- """
-
- def __init__(
- self,
- model,
- strategy: Strategy,
- optim: Optimizer,
- loss_fn,
- train_dataset: Dataset,
- valid_dataset: Dataset,
- eval_dataset: Dataset,
- batch_size: int = 1,
- max_epochs: int = 1,
- ) -> None:
- super().__init__()
- self.strategy = strategy
- self.epochs = max_epochs
- train_sampler = None
-
- if dist.is_initialized() and dist.get_world_size() > 1:
- train_sampler = DistributedSampler(train_dataset, shuffle=True, seed=42, drop_last=True)
- self.train_dataloader = DataLoader(train_dataset,
- shuffle=(train_sampler is None),
- sampler=train_sampler,
- batch_size=batch_size)
- self.valid_dataloader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=True)
- self.eval_dataloader = DataLoader(eval_dataset, batch_size=batch_size, shuffle=True)
-
- self.model = strategy.setup_model(model)
- self.loss_fn = loss_fn
- self.optimizer = strategy.setup_optimizer(optim, self.model)
- self.scheduler = lr_scheduler.CosineAnnealingLR(self.optimizer, self.train_dataloader.__len__() // 100)
-
- def eval_acc(self, dataloader):
- dist = 0
- on = 0
- cnt = 0
- self.model.eval()
- with torch.no_grad():
- for chosen_ids, c_mask, reject_ids, r_mask in dataloader:
- chosen_ids = chosen_ids.squeeze(1).to(torch.cuda.current_device())
- c_mask = c_mask.squeeze(1).to(torch.cuda.current_device())
- reject_ids = reject_ids.squeeze(1).to(torch.cuda.current_device())
- r_mask = r_mask.squeeze(1).to(torch.cuda.current_device())
- chosen_reward = self.model(chosen_ids, attention_mask=c_mask)
- reject_reward = self.model(reject_ids, attention_mask=r_mask)
- for i in range(len(chosen_reward)):
- cnt += 1
- if chosen_reward[i] > reject_reward[i]:
- on += 1
- dist += (chosen_reward - reject_reward).mean().item()
- dist_mean = dist / len(dataloader)
- acc = on / cnt
- self.model.train()
- return dist_mean, acc
-
- def fit(self):
- time = datetime.now()
- epoch_bar = tqdm(range(self.epochs), desc='Train epoch', disable=not is_rank_0())
- for epoch in range(self.epochs):
- step_bar = tqdm(range(self.train_dataloader.__len__()),
- desc='Train step of epoch %d' % epoch,
- disable=not is_rank_0())
- # train
- self.model.train()
- cnt = 0
- acc = 0
- dist = 0
- for chosen_ids, c_mask, reject_ids, r_mask in self.train_dataloader:
- chosen_ids = chosen_ids.squeeze(1).to(torch.cuda.current_device())
- c_mask = c_mask.squeeze(1).to(torch.cuda.current_device())
- reject_ids = reject_ids.squeeze(1).to(torch.cuda.current_device())
- r_mask = r_mask.squeeze(1).to(torch.cuda.current_device())
- chosen_reward = self.model(chosen_ids, attention_mask=c_mask)
- reject_reward = self.model(reject_ids, attention_mask=r_mask)
- loss = self.loss_fn(chosen_reward, reject_reward)
- self.strategy.backward(loss, self.model, self.optimizer)
- self.strategy.optimizer_step(self.optimizer)
- self.optimizer.zero_grad()
- cnt += 1
- if cnt == 100:
- self.scheduler.step()
- dist, acc = self.eval_acc(self.valid_dataloader)
- cnt = 0
- if is_rank_0():
- log = pd.DataFrame([[step_bar.n, loss.item(), dist, acc]],
- columns=['step', 'loss', 'dist', 'acc'])
- log.to_csv('log_%s.csv' % time, mode='a', header=False, index=False)
- step_bar.update()
- step_bar.set_postfix({'dist': dist, 'acc': acc})
-
- # eval
- dist, acc = self.eval_acc(self.eval_dataloader)
- if is_rank_0():
- log = pd.DataFrame([[step_bar.n, loss.item(), dist, acc]], columns=['step', 'loss', 'dist', 'acc'])
- log.to_csv('log.csv', mode='a', header=False, index=False)
- epoch_bar.update()
- step_bar.set_postfix({'dist': dist, 'acc': acc})
- step_bar.close()
-
- def save_model(self,
- path: str,
- only_rank0: bool = False,
- tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- self.strategy.save_model(model=self.model, path=path, only_rank0=only_rank0, tokenizer=tokenizer)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/sft.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/sft.py
deleted file mode 100644
index 8eeffea48..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/sft.py
+++ /dev/null
@@ -1,158 +0,0 @@
-import math
-import time
-from abc import ABC
-from typing import Optional
-
-import loralib as lora
-import torch
-import torch.distributed as dist
-import wandb
-from coati.models.loss import GPTLMLoss
-from torch import nn
-from torch.optim import Adam, Optimizer
-from torch.optim.lr_scheduler import LambdaLR
-from torch.utils.data import DataLoader
-from torch.utils.data.distributed import DistributedSampler
-from tqdm import tqdm
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-from transformers.trainer import get_scheduler
-
-from colossalai.logging import get_dist_logger
-
-from .strategies import Strategy
-from .utils import is_rank_0
-
-
-class SFTTrainer(ABC):
- """
- Trainer to use while training reward model.
-
- Args:
- model (torch.nn.Module): the model to train
- strategy (Strategy): the strategy to use for training
- optim(Optimizer): the optimizer to use for training
- train_dataloader: the dataloader to use for training
- eval_dataloader: the dataloader to use for evaluation
- batch_size (int, defaults to 1): the batch size while training
- max_epochs (int, defaults to 2): the number of epochs to train
- optim_kwargs (dict, defaults to {'lr':1e-4}): the kwargs to use while initializing optimizer
- """
-
- def __init__(
- self,
- model,
- strategy: Strategy,
- optim: Optimizer,
- train_dataloader: DataLoader,
- eval_dataloader: DataLoader = None,
- batch_size: int = 1,
- max_epochs: int = 2,
- accimulation_steps: int = 8,
- ) -> None:
- super().__init__()
- self.strategy = strategy
- self.epochs = max_epochs
- self.train_dataloader = train_dataloader
- self.eval_dataloader = eval_dataloader
-
- self.model = strategy.setup_model(model)
- if "DDP" in str(self.strategy):
- self.model = self.model.module
- self.optimizer = strategy.setup_optimizer(optim, self.model)
-
- self.accimulation_steps = accimulation_steps
- num_update_steps_per_epoch = len(train_dataloader) // self.accimulation_steps
- max_steps = math.ceil(self.epochs * num_update_steps_per_epoch)
-
- self.scheduler = get_scheduler("cosine",
- self.optimizer,
- num_warmup_steps=math.ceil(max_steps * 0.03),
- num_training_steps=max_steps)
-
- def fit(self, logger, log_interval=10):
- wandb.init(project="Coati", name=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
- wandb.watch(self.model)
- total_loss = 0
- # epoch_bar = tqdm(range(self.epochs), desc='Epochs', disable=not is_rank_0())
- step_bar = tqdm(range(len(self.train_dataloader) // self.accimulation_steps * self.epochs),
- desc=f'steps',
- disable=not is_rank_0())
- for epoch in range(self.epochs):
-
- # process_bar = tqdm(range(len(self.train_dataloader)), desc=f'Train process for{epoch}', disable=not is_rank_0())
- # train
- self.model.train()
- for batch_id, batch in enumerate(self.train_dataloader):
-
- prompt_ids = batch["input_ids"].to(torch.cuda.current_device())
- p_mask = batch["attention_mask"].to(torch.cuda.current_device())
- labels = batch["labels"].to(torch.cuda.current_device())
- # prompt_ids = prompt_ids.squeeze(1).cuda()
- # p_mask = p_mask.squeeze(1).cuda()
- # prompt_logits = self.model(prompt_ids, attention_mask=p_mask, labels=labels)
-
- outputs = self.model(prompt_ids, attention_mask=p_mask, labels=labels)
-
- loss = outputs.loss
- prompt_logits = outputs.logits
-
- if loss >= 2.5:
- logger.warning(f"batch_id:{batch_id}, abnormal loss: {loss}")
-
- loss = loss / self.accimulation_steps
-
- self.strategy.backward(loss, self.model, self.optimizer)
-
- total_loss += loss.item()
-
- # gradient accumulation
- if (batch_id + 1) % self.accimulation_steps == 0:
- self.strategy.optimizer_step(self.optimizer)
- self.optimizer.zero_grad()
- self.scheduler.step()
- wandb.log({
- "loss": total_loss / self.accimulation_steps,
- "lr": self.scheduler.get_last_lr()[0],
- "epoch": epoch,
- "batch_id": batch_id
- })
- total_loss = 0
- step_bar.update()
-
- # if batch_id % log_interval == 0:
- # logger.info(f'Train Epoch {epoch}/{self.epochs} Batch {batch_id} Rank {dist.get_rank()} loss {loss.item()}')
- # wandb.log({"loss": loss.item()})
-
- # process_bar.update()
-
- # eval
- if self.eval_dataloader is not None:
- self.model.eval()
- with torch.no_grad():
- loss_sum = 0
- num_seen = 0
- for batch in self.eval_dataloader:
- prompt_ids = batch["input_ids"].to(torch.cuda.current_device())
- p_mask = batch["attention_mask"].to(torch.cuda.current_device())
- labels = batch["labels"].to(torch.cuda.current_device())
- # prompt_ids = prompt_ids.squeeze(1).cuda()
- # p_mask = p_mask.squeeze(1).cuda()
-
- outputs = self.model(prompt_ids, attention_mask=p_mask, labels=labels)
- loss = outputs.loss
- # prompt_logits = outputs.logits
-
- loss_sum += loss.item()
- num_seen += prompt_ids.size(0)
-
- loss_mean = loss_sum / num_seen
- if dist.get_rank() == 0:
- logger.info(f'Eval Epoch {epoch}/{self.epochs} loss {loss_mean}')
-
- # epoch_bar.update()
-
- def save_model(self,
- path: str,
- only_rank0: bool = False,
- tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- self.strategy.save_model(model=self.model, path=path, only_rank0=only_rank0, tokenizer=tokenizer)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/__init__.py
deleted file mode 100644
index f258c9b8a..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .base import Strategy
-from .colossalai import ColossalAIStrategy
-from .ddp import DDPStrategy
-from .naive import NaiveStrategy
-
-__all__ = ['Strategy', 'NaiveStrategy', 'DDPStrategy', 'ColossalAIStrategy']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/base.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/base.py
deleted file mode 100644
index 7d2513856..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/base.py
+++ /dev/null
@@ -1,136 +0,0 @@
-from abc import ABC, abstractmethod
-from contextlib import nullcontext
-from typing import Any, List, Optional, Tuple, Union
-
-import numpy as np
-import torch
-import torch.nn as nn
-from coati.models.base import LM, Actor, Critic, RewardModel
-from coati.replay_buffer import ReplayBuffer
-from torch.optim import Optimizer
-from torch.utils.data import DataLoader
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .sampler import DistributedSampler
-
-ModelOptimPair = Tuple[nn.Module, Optimizer]
-ModelOrModelOptimPair = Union[nn.Module, ModelOptimPair]
-
-
-class Strategy(ABC):
- """
- Base class for training strategies.
- """
-
- def __init__(self) -> None:
- super().__init__()
- self.setup_distributed()
-
- @abstractmethod
- def backward(self, loss: torch.Tensor, model: nn.Module, optimizer: Optimizer, **kwargs) -> None:
- pass
-
- @abstractmethod
- def optimizer_step(self, optimizer: Optimizer, **kwargs) -> None:
- pass
-
- @abstractmethod
- def setup_distributed(self) -> None:
- pass
-
- @abstractmethod
- def setup_model(self, model: nn.Module) -> nn.Module:
- pass
-
- @abstractmethod
- def setup_optimizer(self, optimizer: Optimizer, model: nn.Module) -> Optimizer:
- pass
-
- @abstractmethod
- def setup_dataloader(self, replay_buffer: ReplayBuffer, pin_memory: bool = False) -> DataLoader:
- pass
-
- def model_init_context(self):
- return nullcontext()
-
- def prepare(
- self, *models_or_model_optim_pairs: ModelOrModelOptimPair
- ) -> Union[List[ModelOrModelOptimPair], ModelOrModelOptimPair]:
- """Prepare models or model-optimizer-pairs based on each strategy.
-
- Example::
- >>> # when fine-tuning actor and critic
- >>> (actor, actor_optim), (critic, critic_optim), reward_model, initial_model = strategy.prepare((actor, actor_optim), (critic, critic_optim), reward_model, initial_model)
- >>> # or when training reward model
- >>> (reward_model, reward_model_optim) = strategy.prepare((reward_model, reward_model_optim))
- >>> # or just inference
- >>> actor, critic = strategy.prepare(actor, critic)
-
- Returns:
- Union[List[ModelOrModelOptimPair], ModelOrModelOptimPair]: Models or model-optimizer-pairs in the original order.
- """
-
- def prepare_model(model: nn.Module):
- if isinstance(model, Actor):
- return Actor(self.setup_model(self._unwrap_model(model)))
- return self.setup_model(self._unwrap_model(model))
-
- rets = []
- for arg in models_or_model_optim_pairs:
- if isinstance(arg, tuple):
- assert len(arg) == 2, f'Expect (model, optimizer) pair, got a tuple with size "{len(arg)}"'
- model, optimizer = arg
- model = prepare_model(model)
- optimizer = self.setup_optimizer(optimizer, self._unwrap_model(model))
- rets.append((model, optimizer))
- elif isinstance(arg, nn.Module):
- rets.append(prepare_model(arg))
- else:
- raise RuntimeError(f'Expect model or (model, optimizer) pair, got {type(arg)}')
-
- if len(rets) == 1:
- return rets[0]
- return rets
-
- @staticmethod
- def _unwrap_model(model: nn.Module) -> nn.Module:
- """Useful for saving state dict. As actor is wrapped by Actor class again in `prepare()`, we should unwrap it before saving.
-
- Args:
- model (nn.Module): an actor or a critic
- """
- if isinstance(model, Actor) or isinstance(model, LM):
- return model.model
- return model
-
- @staticmethod
- def _unwrap_actor(actor: Actor) -> nn.Module:
- """Get `actor.model` from a wrapped (by `prepare()`) actor. Useful for getting original huggingface model.
-
- Args:
- actor (Actor): a wrapped actor
- """
- return Strategy._unwrap_model(actor)
-
- @abstractmethod
- def save_model(self,
- model: nn.Module,
- path: str,
- only_rank0: bool = False,
- tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- pass
-
- @abstractmethod
- def load_model(self, model: nn.Module, path: str, map_location: Any = None, strict: bool = True) -> None:
- pass
-
- @abstractmethod
- def save_optimizer(self, optimizer: Optimizer, path: str, only_rank0: bool = False) -> None:
- pass
-
- @abstractmethod
- def load_optimizer(self, optimizer: Optimizer, path: str, map_location: Any = None) -> None:
- pass
-
- def setup_sampler(self, dataset) -> DistributedSampler:
- return DistributedSampler(dataset, 1, 0)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/colossalai.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/colossalai.py
deleted file mode 100644
index ba85ba76d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/colossalai.py
+++ /dev/null
@@ -1,212 +0,0 @@
-import warnings
-from typing import Optional, Union
-
-import torch
-import torch.distributed as dist
-import torch.nn as nn
-import torch.optim as optim
-from coati.models.base import LM, Actor, RewardModel
-from coati.models.lora import LoraLinear
-from torch.optim import Optimizer
-from transformers.modeling_utils import PreTrainedModel
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-import colossalai
-from colossalai.logging import get_dist_logger
-from colossalai.nn.optimizer import CPUAdam, HybridAdam
-from colossalai.tensor import ProcessGroup, ShardSpec
-from colossalai.utils import get_current_device
-from colossalai.zero import ColoInitContext, ZeroDDP, zero_model_wrapper, zero_optim_wrapper
-from colossalai.zero.gemini.utils import get_static_torch_model
-
-from .base import Strategy
-from .ddp import DDPStrategy
-
-logger = get_dist_logger(__name__)
-
-
-class ColossalAIStrategy(DDPStrategy):
- """
- The strategy for training with ColossalAI.
-
- Args:
- stage(int): The stage to use in ZeRO. Choose in (1, 2, 3)
- precision(str): The precision to use. Choose in ('fp32', 'fp16'). Stage 3 only supports fp16.
- seed(int): The seed for the random number generator.
- shard_init(bool): Whether to shard the model parameters during initialization. Only for ZeRO-3.
- This is not compativle with `from_pretrained()`. We temporarily disable this and will support it in the future.
- placement_policy(str): The placement policy for gemini. Choose in ('cpu', 'cuda')
- If it is “cpu”, parameters, gradients and optimizer states will be offloaded to CPU,
- If it is “cuda”, they will not be offloaded, which means max CUDA memory will be used. It is the fastest.
- pin_memory(bool): Whether to pin the memory for the data loader. Only for ZeRO-3.
- force_outputs_fp32(bool): Whether to force the outputs to be fp32. Only for ZeRO-3.
- search_range_mb(int): The search range in MB for the chunk size. Only for ZeRO-3.
- hidden_dim(optional, int): The hidden dimension for the gemini. Only for ZeRO-3.
- min_chunk_size_mb(float): The minimum chunk size in MB. Only for ZeRO-3.
- gpu_margin_mem_ratio(float): The margin memory ratio for the GPU. Only for ZeRO-3.
- reduce_bugket_size(int): The reduce bucket size in bytes. Only for ZeRO-1 and ZeRO-2.
- overlap_communication(bool): Whether to overlap communication and computation. Only for ZeRO-1 and ZeRO-2.
- initial_scale(float): The initial scale for the optimizer.
- growth_factor(float): The growth factor for the optimizer.
- backoff_factor(float): The backoff factor for the optimizer.
- growth_interval(int): The growth interval for the optimizer.
- hysteresis(int): The hysteresis for the optimizer.
- min_scale(float): The minimum scale for the optimizer.
- max_scale(float): The maximum scale for the optimizer.
- max_norm(float): The maximum norm for the optimizer.
- norm_type(float): The norm type for the optimizer.
-
- """
-
- def __init__(
- self,
- stage: int = 3,
- precision: str = 'fp16',
- seed: int = 42,
- shard_init: bool = False, # only for stage 3
- placement_policy: str = 'cuda',
- pin_memory: bool = True, # only for stage 3
- force_outputs_fp32: bool = False, # only for stage 3
- search_range_mb: int = 32, # only for stage 3
- hidden_dim: Optional[int] = None, # only for stage 3
- min_chunk_size_mb: float = 32, # only for stage 3
- gpu_margin_mem_ratio: float = 0.0, # only for stage 3
- reduce_bucket_size: int = 12 * 1024**2, # only for stage 1&2
- overlap_communication: bool = True, # only for stage 1&2
- initial_scale: float = 2**16,
- growth_factor: float = 2,
- backoff_factor: float = 0.5,
- growth_interval: int = 1000,
- hysteresis: int = 2,
- min_scale: float = 1,
- max_scale: float = 2**32,
- max_norm: float = 0.0,
- norm_type: float = 2.0) -> None:
- super().__init__(seed)
- assert placement_policy in ('cpu', 'cuda'), f'Unsupported placement policy "{placement_policy}"'
- assert precision in ('fp32', 'fp16'), f'Unsupported precision "{precision}"'
- self.stage = stage
- # TODO(ver217): support shard_init when using from_pretrained()
- if shard_init:
- warnings.warn(
- f'Shard init is not supported model.from_pretrained() yet. Please load weights after strategy.prepare()'
- )
- if stage == 3 and precision == 'fp32':
- warnings.warn(f'Stage 3 only supports fp16. Precision is set to fp16.')
- precision = 'fp16'
- self.precision = precision
- self.shard_init = shard_init
- self.gemini_config = dict(device=get_current_device(),
- placement_policy=placement_policy,
- pin_memory=pin_memory,
- force_outputs_fp32=force_outputs_fp32,
- strict_ddp_mode=shard_init,
- search_range_mb=search_range_mb,
- hidden_dim=hidden_dim,
- min_chunk_size_mb=min_chunk_size_mb)
- if stage == 3:
- self.zero_optim_config = dict(gpu_margin_mem_ratio=gpu_margin_mem_ratio)
- else:
- self.zero_optim_config = dict(reduce_bucket_size=reduce_bucket_size,
- overlap_communication=overlap_communication,
- cpu_offload=(placement_policy == 'cpu'))
- self.optim_kwargs = dict(initial_scale=initial_scale,
- growth_factor=growth_factor,
- backoff_factor=backoff_factor,
- growth_interval=growth_interval,
- hysteresis=hysteresis,
- min_scale=min_scale,
- max_scale=max_scale,
- max_norm=max_norm,
- norm_type=norm_type)
-
- def setup_distributed(self) -> None:
- colossalai.launch_from_torch({}, seed=self.seed)
-
- def model_init_context(self):
- if self.stage == 3:
- world_size = dist.get_world_size()
- shard_pg = ProcessGroup(tp_degree=world_size) if self.shard_init else None
- default_dist_spec = ShardSpec([-1], [world_size]) if self.shard_init else None
- return ColoInitContext(device=get_current_device(),
- dtype=torch.half,
- default_pg=shard_pg,
- default_dist_spec=default_dist_spec)
- return super().model_init_context()
-
- def setup_model(self, model: nn.Module) -> nn.Module:
-
- model = zero_model_wrapper(model, zero_stage=self.stage, gemini_config=self.gemini_config)
-
- if self.stage != 3 and self.precision == 'fp16':
- model = model.half()
- return model
-
- def setup_optimizer(self, optimizer: optim.Optimizer, model: nn.Module) -> optim.Optimizer:
- assert isinstance(optimizer, (CPUAdam, HybridAdam)), f'Unsupported optimizer {type(optimizer)}'
- return zero_optim_wrapper(model, optimizer, optim_config=self.zero_optim_config, **self.optim_kwargs)
-
- def backward(self, loss: torch.Tensor, model: nn.Module, optimizer: optim.Optimizer, **kwargs) -> None:
- optimizer.backward(loss)
-
- def optimizer_step(self, optimizer: optim.Optimizer, **kwargs) -> None:
- optimizer.step()
-
- @staticmethod
- def _unwrap_actor(actor: Actor) -> nn.Module:
- model: Union[nn.Module, ZeroDDP] = Strategy._unwrap_actor(actor)
- if isinstance(model, ZeroDDP):
- return model.module
- return model
-
- def _unwrap_model(self, model: Union[nn.Module, ZeroDDP]) -> nn.Module:
- if isinstance(model, ZeroDDP) and self.stage == 3:
- logger.info(f"model type: {type(model)}, get static torch model")
- model = get_static_torch_model(model)
- logger.info(f"unwrapped_model type: {type(model)}")
-
- return super()._unwrap_model(model)
-
- def save_model(self,
- model: nn.Module,
- path: str,
- only_rank0: bool = True,
- tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
-
- if only_rank0 and dist.get_rank() != 0:
- return None
- unwrapped_model = self._unwrap_model(model)
- # TODO : better way to get torch model from gemini model
- # to get torch model from gemini model
-
- for module in unwrapped_model.modules():
- if isinstance(module, LoraLinear):
- module.merge_weights = True
- module.eval()
- if isinstance(unwrapped_model, RewardModel):
- state_dict = unwrapped_model.state_dict()
- if only_rank0 and dist.get_rank() != 0:
- return
- torch.save(state_dict, path)
- else:
- try:
- if isinstance(unwrapped_model, LM):
- unwrapped_model = unwrapped_model.model
- logger.info(f'Saving model to {path}', ranks=[0])
- unwrapped_model.save_pretrained(path)
- logger.info(f'Model saved to {path} Successfully', ranks=[0])
- if tokenizer is not None:
- logger.info(f'Saving tokenizer to {path}', ranks=[0])
- tokenizer.save_pretrained(path)
- logger.info(f'Tokenizer saved to {path} Successfully', ranks=[0])
- except AttributeError:
- state_dict = unwrapped_model.state_dict()
- if only_rank0 and dist.get_rank() != 0:
- return
- torch.save(state_dict, path)
-
- def save_optimizer(self, optimizer: Optimizer, path: str, only_rank0: bool = False) -> None:
- if only_rank0:
- raise RuntimeError(
- f'Optimizer states are sharded when using ColossalAIStrategy. Only rank0 is not supported.')
- torch.save(optimizer.state_dict(), path)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/ddp.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/ddp.py
deleted file mode 100644
index 7bf8e8ba8..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/ddp.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from typing import Optional
-
-import os
-import random
-
-import numpy as np
-import torch
-import torch.distributed as dist
-import torch.nn as nn
-from coati.models.base import LM, Actor, RewardModel
-from coati.models.lora import LoraLinear
-from coati.replay_buffer import ReplayBuffer
-from torch.nn.parallel import DistributedDataParallel as DDP
-from torch.optim import Optimizer
-from torch.utils.data import DataLoader
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .base import Strategy
-from .naive import NaiveStrategy
-from .sampler import DistributedSampler
-
-
-class DDPStrategy(NaiveStrategy):
- """
- Strategy for distributed training using torch.distributed.
- """
-
- def __init__(self, seed: int = 42) -> None:
- self.seed = seed
- super().__init__()
-
- def setup_distributed(self) -> None:
- try:
- rank = int(os.environ['RANK'])
- local_rank = int(os.environ['LOCAL_RANK'])
- world_size = int(os.environ['WORLD_SIZE'])
- host = os.environ['MASTER_ADDR']
- port = int(os.environ['MASTER_PORT'])
- except KeyError as e:
- raise RuntimeError(
- f"Could not find {e} in the torch environment, visit https://www.colossalai.org/ for more information on launching with torch"
- )
- dist.init_process_group('nccl', init_method=f'tcp://[{host}]:{port}', world_size=world_size, rank=rank)
- self.set_seed(self.seed)
- torch.cuda.set_device(local_rank)
-
- def set_seed(self, seed: int) -> None:
- random.seed(seed)
- np.random.seed(seed)
- torch.manual_seed(seed)
-
- def setup_model(self, model: nn.Module) -> nn.Module:
- device = torch.cuda.current_device()
- return DDP(model, device_ids=[device])
-
- def setup_dataloader(self, replay_buffer: ReplayBuffer, pin_memory: bool = False) -> DataLoader:
- # DDP only mode, replay buffers on each rank are different.
- # sampler = DistributedSampler(replay_buffer,
- # num_replicas=dist.get_world_size(),
- # rank=dist.get_rank(),
- # shuffle=True,
- # seed=self.seed,
- # drop_last=True)
- return DataLoader(
- replay_buffer,
- batch_size=replay_buffer.sample_batch_size,
- # sampler=sampler,
- shuffle=True,
- drop_last=True,
- pin_memory=pin_memory,
- collate_fn=replay_buffer.collate_fn)
-
- @staticmethod
- def _unwrap_actor(actor: Actor) -> nn.Module:
- model: DDP = Strategy._unwrap_actor(actor)
- return model.module
-
- def save_model(self, model: nn.Module, path: str, only_rank0: bool = False, tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- if only_rank0 and dist.get_rank() != 0:
- return None
-
- for module in model.modules():
- if isinstance(module, LoraLinear):
- module.merge_weights = True
- module.eval()
-
- if isinstance(model, RewardModel):
- state_dict = model.state_dict()
- if only_rank0 and dist.get_rank() != 0:
- return
- torch.save(state_dict, path)
- else:
- try:
- if isinstance(model, LM):
- model = model.model
- model.save_pretrained(path)
- if tokenizer is not None:
- tokenizer.save_pretrained(path)
- except AttributeError:
- state_dict = model.state_dict()
- if only_rank0 and dist.get_rank() != 0:
- return
- torch.save(state_dict, path)
-
- def save_optimizer(self, optimizer: Optimizer, path: str, only_rank0: bool = False) -> None:
- if only_rank0 and dist.get_rank() != 0:
- return
- super().save_optimizer(optimizer, path, only_rank0)
-
- def setup_sampler(self, dataset) -> DistributedSampler:
- return DistributedSampler(dataset, dist.get_world_size(), dist.get_rank())
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/naive.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/naive.py
deleted file mode 100644
index 3a86b13c0..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/naive.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from typing import Any, Optional
-
-import torch
-import torch.nn as nn
-import torch.optim as optim
-from coati.replay_buffer import ReplayBuffer
-from coati.models.base import LM, RewardModel
-from coati.models.lora import LoraLinear
-from torch.optim import Optimizer
-from torch.utils.data import DataLoader
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .base import Strategy
-
-
-class NaiveStrategy(Strategy):
- """
- Strategy for single GPU. No parallelism is used.
- """
-
- def backward(self, loss: torch.Tensor, model: nn.Module, optimizer: optim.Optimizer, **kwargs) -> None:
- loss.backward()
-
- def optimizer_step(self, optimizer: optim.Optimizer, **kwargs) -> None:
- optimizer.step()
-
- def setup_distributed(self) -> None:
- pass
-
- def setup_model(self, model: nn.Module) -> nn.Module:
- return model
-
- def setup_optimizer(self, optimizer: optim.Optimizer, model: nn.Module) -> optim.Optimizer:
- return optimizer
-
- def setup_dataloader(self, replay_buffer: ReplayBuffer, pin_memory: bool = False) -> DataLoader:
- return DataLoader(replay_buffer,
- batch_size=replay_buffer.sample_batch_size,
- shuffle=True,
- drop_last=True,
- pin_memory=pin_memory,
- collate_fn=replay_buffer.collate_fn)
-
- def save_model(self, model: nn.Module, path: str, only_rank0: bool = False, tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- for module in model.modules():
- if isinstance(module, LoraLinear):
- module.merge_weights = True
- module.eval()
-
- if isinstance(model, RewardModel):
- state_dict = model.state_dict()
- torch.save(state_dict, path)
- else:
- try:
- if isinstance(model, LM):
- model = model.model
- model.save_pretrained(path)
- if tokenizer is not None:
- tokenizer.save_pretrained(path)
- except AttributeError:
- state_dict = model.state_dict()
- torch.save(state_dict, path)
-
- def load_model(self, model: nn.Module, path: str, map_location: Any = None, strict: bool = True) -> None:
- unwrapped_model = self._unwrap_model(model)
- state_dict = torch.load(path, map_location=map_location)
- unwrapped_model.load_state_dict(state_dict, strict=strict)
-
- def save_optimizer(self, optimizer: Optimizer, path: str, only_rank0: bool = False) -> None:
- torch.save(optimizer.state_dict(), path)
-
- def load_optimizer(self, optimizer: Optimizer, path: str, map_location: Any = None) -> None:
- state_dict = torch.load(path, map_location=map_location)
- optimizer.load_state_dict(state_dict)
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/sampler.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/sampler.py
deleted file mode 100644
index d726fa640..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/strategies/sampler.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import math
-
-import numpy as np
-
-
-class DistributedSampler:
-
- def __init__(self, dataset, num_replicas: int, rank: int) -> None:
- self.dataset = dataset
- self.num_replicas = num_replicas
- self.rank = rank
-
- if len(self.dataset) % self.num_replicas != 0:
- self.num_samples = math.ceil(
- (len(self.dataset) - self.num_replicas) / self.num_replicas # type: ignore[arg-type]
- )
- else:
- self.num_samples = math.ceil(len(self.dataset) / self.num_replicas)
-
- self.total_size = self.num_samples * self.num_replicas
-
- indices = list(range(len(self.dataset)))
- indices = indices[:self.total_size]
- assert len(indices) == self.total_size
- # subsample
- indices = indices[self.rank:self.total_size:self.num_replicas]
- assert len(indices) == self.num_samples
- self.indices = indices
-
- def sample(self, batch_size: int) -> list:
- sampled_indices = np.random.choice(self.indices, batch_size, replace=False)
- return [self.dataset[idx] for idx in sampled_indices]
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/utils.py
deleted file mode 100644
index 6c9f7f085..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/trainer/utils.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import torch.distributed as dist
-
-
-def is_rank_0() -> bool:
- return not dist.is_initialized() or dist.get_rank() == 0
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/utils/__init__.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/utils/__init__.py
deleted file mode 100644
index e75401d38..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/utils/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .tokenizer_utils import prepare_llama_tokenizer_and_embedding, smart_tokenizer_and_embedding_resize
-
-__all__ = ['smart_tokenizer_and_embedding_resize', 'prepare_llama_tokenizer_and_embedding']
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/utils/tokenizer_utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/utils/tokenizer_utils.py
deleted file mode 100644
index 35ebb96af..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/coati/utils/tokenizer_utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2023 Rohan Taori, Ishaan Gulrajani, Tianyi Zhang, Yann Dubois, Xuechen Li
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from typing import Dict
-
-import transformers
-
-from ..models.llama.llama_lm import LlamaLM
-
-DEFAULT_PAD_TOKEN = "[PAD]"
-DEFAULT_EOS_TOKEN = ""
-DEFAULT_BOS_TOKEN = ""
-DEFAULT_UNK_TOKEN = ""
-
-
-def prepare_llama_tokenizer_and_embedding(
- tokenizer: transformers.PreTrainedTokenizer,
- model: transformers.PreTrainedModel,
- special_tokens_dict: Dict = dict(pad_token=DEFAULT_PAD_TOKEN),
-):
- """prepare llama tokenizer and embedding.
-
- """
-
- if tokenizer.pad_token is None:
- smart_tokenizer_and_embedding_resize(
- special_tokens_dict=dict(pad_token=DEFAULT_PAD_TOKEN),
- tokenizer=tokenizer,
- model=model,
- )
-
- tokenizer.add_special_tokens({
- "eos_token": DEFAULT_EOS_TOKEN,
- "bos_token": DEFAULT_BOS_TOKEN,
- "unk_token": DEFAULT_UNK_TOKEN,
- })
-
- return tokenizer
-
-
-def smart_tokenizer_and_embedding_resize(
- tokenizer: transformers.PreTrainedTokenizer,
- model: transformers.PreTrainedModel,
- special_tokens_dict: Dict = dict(pad_token=DEFAULT_PAD_TOKEN),
-):
- """Resize tokenizer and embedding.
-
- Note: This is the unoptimized version that may make your embedding size not be divisible by 64.
- """
-
- if tokenizer.pad_token is None:
- num_new_tokens = tokenizer.add_special_tokens(special_tokens_dict)
-
- if isinstance(model, LlamaLM):
- model = model.get_base_model()
-
- model.model.resize_token_embeddings(len(tokenizer))
-
- if num_new_tokens > 0:
- input_embeddings = model.model.get_input_embeddings().weight.data
- output_embeddings = model.model.get_output_embeddings().weight.data
-
- input_embeddings_avg = input_embeddings[:-num_new_tokens].mean(dim=0, keepdim=True)
- output_embeddings_avg = output_embeddings[:-num_new_tokens].mean(dim=0, keepdim=True)
-
- input_embeddings[-num_new_tokens:] = input_embeddings_avg
- output_embeddings[-num_new_tokens:] = output_embeddings_avg
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/neuron.py
deleted file mode 100644
index 1f8123435..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/neuron.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-# General.
-import os
-import json
-import time
-import torch
-import argparse
-import bittensor
-
-from typing import List, Dict
-from rich import print
-from datetime import datetime
-
-# Torch tooling.
-from torch.nn.utils.rnn import pad_sequence
-from torch.optim import Adam
-from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
-
-# Coati PPO tooling.
-from coati.models.auto import AutoActor as Actor, AutoCritic as Critic
-from coati.trainer.strategies import ColossalAIStrategy, DDPStrategy, NaiveStrategy
-from coati.models.loss import PolicyLoss, ValueLoss
-
-# Check run config.
-def check_config(config: 'bittensor.Config'):
- bittensor.logging.check_config(config)
- bittensor.wallet.check_config(config)
- bittensor.subtensor.check_config(config)
- bittensor.metagraph.check_config(config)
- bittensor.axon.check_config(config)
- full_path = os.path.expanduser(
- '{}/{}/{}/{}'.format(config.logging.logging_dir, config.wallet.get('name', bittensor.defaults.wallet.name),
- config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey), config.neuron.name))
- config.neuron.full_path = os.path.expanduser(full_path)
- if not os.path.exists(config.neuron.full_path):
- os.makedirs(config.neuron.full_path)
-
-
-# Create run config.
-def get_config():
- parser = argparse.ArgumentParser()
- parser.add_argument('--netuid', type=int, help='Subnet netuid', default=21)
- parser.add_argument('--config', type=str, help='If set, defaults are overridden by passed file.')
- parser.add_argument('--neuron.name', type=str,
- help='Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name ',
- default='robert_myers_prompting_miner')
- parser.add_argument('--neuron.blocks_per_epoch', type=str, help='Blocks until the miner sets weights on chain',
- default=100)
- parser.add_argument('--neuron.no_set_weights', action='store_true', help='If True, the model does not set weights.',
- default=False)
- parser.add_argument('--neuron.max_batch_size', type=int, help='The maximum batch size for forward requests.',
- default=-1)
- parser.add_argument('--neuron.max_sequence_len', type=int, help='The maximum sequence length for forward requests.',
- default=-1)
- parser.add_argument('--neuron.blacklist.hotkeys', type=str, required=False, nargs='*', action='store',
- help='To blacklist certain hotkeys', default=[])
- parser.add_argument('--neuron.lora_rank', type=int, help='The rank of the lora layer.', default=0)
-
- bittensor.wallet.add_args(parser)
- bittensor.axon.add_args(parser)
- bittensor.subtensor.add_args(parser)
- bittensor.logging.add_args(parser)
- bittensor.metagraph.add_args(parser)
- # bittensor.TextPromptingSynapse.add_args(parser)
- return bittensor.config(parser)
-
-
-
-# Main entry point for model serving.
-def main():
- # --- Build, Check, Set and Print the run config.
- config = get_config()
- config.to_defaults()
- check_config(config)
- print(config)
-
- # --- PPO
- strategy = NaiveStrategy()
-
- # --- Turn on logging.
- bittensor.logging(config=config, logging_dir=config.neuron.full_path)
-
- # --- Create our chain connection.
- subtensor = bittensor.subtensor(config)
-
- # --- Create our wallet and register it to the subnetwork.
- wallet = bittensor.wallet(config)
- wallet.register(netuid=config.netuid, subtensor=subtensor)
-
- # --- Create our network state cache
- metagraph = bittensor.metagraph(config=config, netuid=config.netuid, )
- metagraph.sync(netuid=config.netuid, subtensor=subtensor).save()
- uid = metagraph.hotkeys.index(wallet.hotkey.ss58_address)
-
- # --- Build /Load our model and set the device.
- with bittensor.__console__.status("Loading huggingface model robertmyers/bpt-sft ..."):
- bittensor.logging.info('Loading', "robertmyers/bpt-sft" )
- tokenizer = AutoTokenizer.from_pretrained( "robertmyers/bpt-sft" )
- actor = Actor( pretrained="robertmyers/bpt-sft", lora_rank=config.neuron.lora_rank )
- critic = Critic( pretrained="robertmyers/bpt-sft", lora_rank=config.neuron.lora_rank, use_action_mask=True )
- actor_optim = Adam(actor.parameters(), lr=1e-7)
- critic_optim = Adam(critic.parameters(), lr=1e-7)
- # model = AutoModelForCausalLM.from_pretrained( "robertmyers/bpt-sft", torch_dtype=torch.float16 )
-
- actor.to( "cuda" )
- pipe = pipeline("text-generation", actor, tokenizer=tokenizer, device=0, max_new_tokens = 256 )
-
- # --- Build axon server and start it.tensor.loggi
- axon = bittensor.axon(
- wallet=wallet,
- metagraph=metagraph,
- config=config,
- )
-
- def _process_history(history: List[str]) -> str:
- processed_history = ''
- for message in history:
- message = json.loads(message)
- if message['role'] == 'system':
- processed_history += 'system: ' + message['content'] + '\n'
-
- if message['role'] == 'assistant':
- processed_history += 'assistant: ' + message['content'] + '\n'
-
- if message['role'] == 'user':
- processed_history += 'user: ' + message['content'] + '\n'
- return processed_history
-
- class Synapse(bittensor.TextPromptingSynapse):
- def _priority(self, forward_call: "bittensor.TextPromptingForwardCall") -> float:
- return 0.0
-
- def _blacklist(self, forward_call: "bittensor.TextPromptingForwardCall") -> bool:
- return False
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- def forward(self, messages: List[str]) -> str:
- history = _process_history(messages)
- return pipe( history )[0]['generated_text'].split(':')[-1].replace( str( history ), "")
-
- syn = Synapse()
- axon.attach(syn)
- axon.start()
- axon.netuid = config.netuid
- axon.protocol = 4
- subtensor.serve_axon( axon )
- print (axon)
-
- # --- Run Forever.
- last_update = subtensor.get_current_block()
- while True:
-
- # --- Wait until next epoch.
- current_block = subtensor.get_current_block()
- while (current_block - last_update) < config.neuron.blocks_per_epoch:
- time.sleep(bittensor.__blocktime__)
- current_block = subtensor.get_current_block()
- last_update = subtensor.get_current_block()
-
- # --- Update the metagraph with the latest network state.
- metagraph.sync(netuid=config.netuid, subtensor=subtensor)
- uid = metagraph.hotkeys.index(wallet.hotkey.ss58_address)
-
- # --- Log performance.
- print(
- f"[white not bold]{datetime.now():%Y-%m-%d %H:%M:%S}[/white not bold]{' ' * 4} | "
- f"{f'UID [bright_cyan]{uid}[/bright_cyan]'.center(16 + len('[bright_cyan][/bright_cyan]'))} | "
- f'[dim white not bold] [green]{str(metagraph.S[uid].item()):.4}[/green] Stake [/dim white not bold]'
- f'[dim white not bold]| [yellow]{str(metagraph.trust[uid].item()) :.3}[/yellow] Trust [/dim white not bold]'
- f'[dim white not bold]| [green]{str(metagraph.incentive[uid].item()):.3}[/green] Incentive [/dim white not bold]')
-
- # --- Set weights.
- if not config.neuron.no_set_weights:
- try:
- # --- query the chain for the most current number of peers on the network
- chain_weights = torch.zeros(subtensor.subnetwork_n(netuid=config.netuid))
- chain_weights[uid] = 1
- did_set = subtensor.set_weights(
- uids=torch.arange(0, len(chain_weights)),
- netuid=config.netuid,
- weights=chain_weights,
- wait_for_inclusion=False,
- wallet=wallet,
- version_key=1
- )
- except:
- pass
-
-
-if __name__ == "__main__":
- bittensor.utils.version_checking()
- main()
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/actor.py
deleted file mode 100644
index be9e9abf1..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/actor.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from typing import Optional
-
-from transformers import AutoConfig, AutoModelForCausalLM
-
-
-from base import Actor
-
-
-class AutoActor(Actor):
- """
- Auto Actor model.
-
- Args:
- pretrained (str): Pretrained model name or path.
- config (AutoConfig): Model config.
- checkpoint (bool): Enable gradient checkpointing.
- lora_rank (int): Rank of the low-rank approximation.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- pretrained: Optional[str] = None,
- config: Optional[AutoConfig] = None,
- checkpoint: bool = False,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- if pretrained is not None:
- model = AutoModelForCausalLM.from_pretrained(pretrained)
- elif config is not None:
- model = AutoModelForCausalLM(config)
- else:
- model = AutoModelForCausalLM(AutoConfig())
- if checkpoint:
- model.gradient_checkpointing_enable()
- super().__init__(model, lora_rank, lora_train_bias)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/actor.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/actor.py
deleted file mode 100644
index 6baf33e4e..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/actor.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from typing import Optional, Tuple, Union
-
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-from ..generation import generate
-from ..lora import LoRAModule
-from ..utils import log_probs_from_logits
-
-
-class Actor(LoRAModule):
- """
- Actor model base class.
-
- Args:
- model (nn.Module): Actor Model.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self, model: nn.Module, lora_rank: int = 0, lora_train_bias: str = 'none') -> None:
- super().__init__(lora_rank=lora_rank, lora_train_bias=lora_train_bias)
- self.model = model
- self.convert_to_lora()
-
- @torch.no_grad()
- def generate(
- self,
- input_ids: torch.Tensor,
- return_action_mask: bool = True,
- **kwargs
- ) -> Union[Tuple[torch.LongTensor, torch.LongTensor], Tuple[torch.LongTensor, torch.LongTensor, torch.BoolTensor]]:
- sequences = generate(self.model, input_ids, **kwargs)
- attention_mask = None
- pad_token_id = kwargs.get('pad_token_id', None)
- if pad_token_id is not None:
- attention_mask = sequences.not_equal(pad_token_id).to(dtype=torch.long, device=sequences.device)
- if not return_action_mask:
- return sequences, attention_mask, None
- input_len = input_ids.size(1)
- eos_token_id = kwargs.get('eos_token_id', None)
- if eos_token_id is None:
- action_mask = torch.ones_like(sequences, dtype=torch.bool)
- else:
- # left padding may be applied, only mask action
- action_mask = (sequences[:, input_len:] == eos_token_id).cumsum(dim=-1) == 0
- action_mask = F.pad(action_mask, (1 + input_len, -1), value=True) # include eos token and input
- action_mask[:, :input_len] = False
- action_mask = action_mask[:, 1:]
- return sequences, attention_mask, action_mask[:, -(sequences.size(1) - input_len):]
-
- def forward(self,
- sequences: torch.LongTensor,
- num_actions: int,
- attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- """Returns action log probs
- """
- output = self.model(sequences, attention_mask=attention_mask)
- logits = output['logits']
- log_probs = log_probs_from_logits(logits[:, :-1, :], sequences[:, 1:])
- return log_probs[:, -num_actions:]
-
- def get_base_model(self):
- return self.model
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/critic.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/critic.py
deleted file mode 100644
index 420cf849d..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/critic.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-
-from ..lora import LoRAModule
-from ..utils import masked_mean
-
-
-class Critic(LoRAModule):
- """
- Critic model base class.
-
- Args:
- model (nn.Module): Critic model.
- value_head (nn.Module): Value head to get value.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(
- self,
- model: nn.Module,
- value_head: nn.Module,
- lora_rank: int = 0,
- lora_train_bias: str = 'none',
- use_action_mask: bool = False,
- ) -> None:
-
- super().__init__(lora_rank=lora_rank, lora_train_bias=lora_train_bias)
- self.model = model
- self.value_head = value_head
- self.use_action_mask = use_action_mask
- self.convert_to_lora()
-
- def forward(self,
- sequences: torch.LongTensor,
- action_mask: Optional[torch.Tensor] = None,
- attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- outputs = self.model(sequences, attention_mask=attention_mask)
- last_hidden_states = outputs['last_hidden_state']
-
- values = self.value_head(last_hidden_states).squeeze(-1)
-
- if action_mask is not None and self.use_action_mask:
- num_actions = action_mask.size(1)
- prompt_mask = attention_mask[:, :-num_actions]
- values = values[:, :-num_actions]
- value = masked_mean(values, prompt_mask, dim=1)
- return value
-
- values = values[:, :-1]
- value = values.mean(dim=1)
- return value
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/lm.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/lm.py
deleted file mode 100644
index 48410a3b3..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/lm.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from typing import Optional, Tuple, Union
-
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-from ..generation import generate
-from .actor import Actor
-
-
-class LM(Actor):
- """
- Language model base class.
-
- Args:
- model (nn.Module): Language Model.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self, model: nn.Module, lora_rank: int = 0, lora_train_bias: str = 'none') -> None:
- super().__init__(model=model, lora_rank=lora_rank, lora_train_bias=lora_train_bias)
-
- def forward(self, sequences: torch.LongTensor, attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- """Returns output log probs
- """
- output = self.model(sequences, attention_mask=attention_mask)
- logits = output['logits']
- log_probs = F.log_softmax(logits, dim=-1)
- return log_probs
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/reward_model.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/reward_model.py
deleted file mode 100644
index 0a4f24ba3..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/base/reward_model.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-
-from ..lora import LoRAModule
-
-
-class RewardModel(LoRAModule):
- """
- Reward model base class.
-
- Args:
- model (nn.Module): Reward model.
- value_head (nn.Module): Value head to get reward score.
- lora_rank (int): LoRA rank.
- lora_train_bias (str): LoRA bias training mode.
- """
-
- def __init__(self,
- model: nn.Module,
- value_head: Optional[nn.Module] = None,
- lora_rank: int = 0,
- lora_train_bias: str = 'none') -> None:
- super().__init__(lora_rank=lora_rank, lora_train_bias=lora_train_bias)
- self.model = model
- self.convert_to_lora()
-
- if value_head is not None:
- if value_head.out_features != 1:
- raise ValueError("The value head of reward model's output dim should be 1!")
- self.value_head = value_head
- else:
- self.value_head = nn.Linear(model.config.n_embd, 1)
-
- def forward(self, sequences: torch.LongTensor, attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- outputs = self.model(sequences, attention_mask=attention_mask)
- last_hidden_states = outputs['last_hidden_state']
- values = self.value_head(last_hidden_states)[:, :-1]
- value = values.mean(dim=1).squeeze(1) # ensure shape is (B)
- return value
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/generation.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/generation.py
deleted file mode 100644
index 73a47d86a..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/generation.py
+++ /dev/null
@@ -1,146 +0,0 @@
-from typing import Any, Callable, Optional
-
-import torch
-import torch.distributed as dist
-import torch.nn as nn
-
-try:
- from transformers.generation_logits_process import (
- LogitsProcessorList,
- TemperatureLogitsWarper,
- TopKLogitsWarper,
- TopPLogitsWarper,
- )
-except ImportError:
- from transformers.generation import LogitsProcessorList, TemperatureLogitsWarper, TopKLogitsWarper, TopPLogitsWarper
-
-
-def prepare_logits_processor(top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- temperature: Optional[float] = None) -> LogitsProcessorList:
- processor_list = LogitsProcessorList()
- if temperature is not None and temperature != 1.0:
- processor_list.append(TemperatureLogitsWarper(temperature))
- if top_k is not None and top_k != 0:
- processor_list.append(TopKLogitsWarper(top_k))
- if top_p is not None and top_p < 1.0:
- processor_list.append(TopPLogitsWarper(top_p))
- return processor_list
-
-
-def _is_sequence_finished(unfinished_sequences: torch.Tensor) -> bool:
- if dist.is_initialized() and dist.get_world_size() > 1:
- # consider DP
- unfinished_sequences = unfinished_sequences.clone()
- dist.all_reduce(unfinished_sequences)
- return unfinished_sequences.max() == 0
-
-
-def sample(model: nn.Module,
- input_ids: torch.Tensor,
- max_length: int,
- early_stopping: bool = False,
- eos_token_id: Optional[int] = None,
- pad_token_id: Optional[int] = None,
- top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- temperature: Optional[float] = None,
- prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,
- update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,
- **model_kwargs) -> torch.Tensor:
- if input_ids.size(1) >= max_length:
- return input_ids
-
- logits_processor = prepare_logits_processor(top_k, top_p, temperature)
- unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1)
-
- for _ in range(input_ids.size(1), max_length):
- model_inputs = prepare_inputs_fn(input_ids, **model_kwargs) if prepare_inputs_fn is not None else {
- 'input_ids': input_ids
- }
- outputs = model(**model_inputs)
-
- next_token_logits = outputs['logits'][:, -1, :]
- # pre-process distribution
- next_token_logits = logits_processor(input_ids, next_token_logits)
- # sample
- probs = torch.softmax(next_token_logits, dim=-1, dtype=torch.float)
- next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1)
-
- # finished sentences should have their next token be a padding token
- if eos_token_id is not None:
- if pad_token_id is None:
- raise ValueError("If `eos_token_id` is defined, make sure that `pad_token_id` is defined.")
- next_tokens = next_tokens * unfinished_sequences + pad_token_id * (1 - unfinished_sequences)
-
- # update generated ids, model inputs for next step
- input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)
- if update_model_kwargs_fn is not None:
- model_kwargs = update_model_kwargs_fn(outputs, **model_kwargs)
-
- # if eos_token was found in one sentence, set sentence to finished
- if eos_token_id is not None:
- unfinished_sequences = unfinished_sequences.mul((next_tokens != eos_token_id).long())
-
- # stop when each sentence is finished if early_stopping=True
- if early_stopping and _is_sequence_finished(unfinished_sequences):
- break
-
- return input_ids
-
-
-def generate(model: nn.Module,
- input_ids: torch.Tensor,
- max_length: int,
- num_beams: int = 1,
- do_sample: bool = True,
- early_stopping: bool = False,
- eos_token_id: Optional[int] = None,
- pad_token_id: Optional[int] = None,
- top_k: Optional[int] = None,
- top_p: Optional[float] = None,
- temperature: Optional[float] = None,
- prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,
- update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,
- **model_kwargs) -> torch.Tensor:
- """Generate token sequence. The returned sequence is input_ids + generated_tokens.
-
- Args:
- model (nn.Module): model
- input_ids (torch.Tensor): input sequence
- max_length (int): max length of the returned sequence
- num_beams (int, optional): number of beams. Defaults to 1.
- do_sample (bool, optional): whether to do sample. Defaults to True.
- early_stopping (bool, optional): if True, the sequence length may be smaller than max_length due to finding eos. Defaults to False.
- eos_token_id (Optional[int], optional): end of sequence token id. Defaults to None.
- pad_token_id (Optional[int], optional): pad token id. Defaults to None.
- top_k (Optional[int], optional): the number of highest probability vocabulary tokens to keep for top-k-filtering. Defaults to None.
- top_p (Optional[float], optional): If set to float < 1, only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation. Defaults to None.
- temperature (Optional[float], optional): The value used to module the next token probabilities. Defaults to None.
- prepare_inputs_fn (Optional[Callable[[torch.Tensor, Any], dict]], optional): Function to preprocess model inputs. Arguments of this function should be input_ids and model_kwargs. Defaults to None.
- update_model_kwargs_fn (Optional[Callable[[dict, Any], dict]], optional): Function to update model_kwargs based on outputs. Arguments of this function should be outputs and model_kwargs. Defaults to None.
- """
- is_greedy_gen_mode = ((num_beams == 1) and do_sample is False)
- is_sample_gen_mode = ((num_beams == 1) and do_sample is True)
- is_beam_gen_mode = ((num_beams > 1) and do_sample is False)
- if is_greedy_gen_mode:
- # run greedy search
- raise NotImplementedError
- elif is_sample_gen_mode:
- # run sample
- return sample(model,
- input_ids,
- max_length,
- early_stopping=early_stopping,
- eos_token_id=eos_token_id,
- pad_token_id=pad_token_id,
- top_k=top_k,
- top_p=top_p,
- temperature=temperature,
- prepare_inputs_fn=prepare_inputs_fn,
- update_model_kwargs_fn=update_model_kwargs_fn,
- **model_kwargs)
- elif is_beam_gen_mode:
- raise NotImplementedError
- else:
- raise ValueError("Unsupported generation mode")
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/generation_utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/generation_utils.py
deleted file mode 100644
index f9f78a6c4..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/generation_utils.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from typing import Optional
-
-import torch
-
-
-def gpt_prepare_inputs_fn(input_ids: torch.Tensor, past: Optional[torch.Tensor] = None, **kwargs) -> dict:
- token_type_ids = kwargs.get("token_type_ids", None)
- # only last token for inputs_ids if past is defined in kwargs
- if past:
- input_ids = input_ids[:, -1].unsqueeze(-1)
- if token_type_ids is not None:
- token_type_ids = token_type_ids[:, -1].unsqueeze(-1)
-
- attention_mask = kwargs.get("attention_mask", None)
- position_ids = kwargs.get("position_ids", None)
-
- if attention_mask is not None and position_ids is None:
- # create position_ids on the fly for batch generation
- position_ids = attention_mask.long().cumsum(-1) - 1
- position_ids.masked_fill_(attention_mask == 0, 1)
- if past:
- position_ids = position_ids[:, -1].unsqueeze(-1)
- else:
- position_ids = None
- return {
- "input_ids": input_ids,
- "past_key_values": past,
- "use_cache": kwargs.get("use_cache"),
- "position_ids": position_ids,
- "attention_mask": attention_mask,
- "token_type_ids": token_type_ids,
- }
-
-
-def update_model_kwargs_fn(outputs: dict, **model_kwargs) -> dict:
- if "past_key_values" in outputs:
- model_kwargs["past"] = outputs["past_key_values"]
- else:
- model_kwargs["past"] = None
-
- # update token_type_ids with last value
- if "token_type_ids" in model_kwargs:
- token_type_ids = model_kwargs["token_type_ids"]
- model_kwargs["token_type_ids"] = torch.cat([token_type_ids, token_type_ids[:, -1].unsqueeze(-1)], dim=-1)
-
- # update attention mask
- if "attention_mask" in model_kwargs:
- attention_mask = model_kwargs["attention_mask"]
- model_kwargs["attention_mask"] = torch.cat(
- [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1)
-
- return model_kwargs
-
-
-def opt_prepare_inputs_fn(input_ids: torch.Tensor,
- past: Optional[torch.Tensor] = None,
- attention_mask: Optional[torch.Tensor] = None,
- use_cache: Optional[bool] = None,
- **kwargs) -> dict:
- # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly
- if attention_mask is None:
- attention_mask = input_ids.new_ones(input_ids.shape)
-
- if past:
- input_ids = input_ids[:, -1:]
- # first step, decoder_cached_states are empty
- return {
- "input_ids": input_ids, # encoder_outputs is defined. input_ids not needed
- "attention_mask": attention_mask,
- "past_key_values": past,
- "use_cache": use_cache,
- }
-
-
-def bloom_prepare_inputs_fn(input_ids: torch.Tensor,
- past: Optional[torch.Tensor] = None,
- attention_mask: Optional[torch.Tensor] = None,
- use_cache: Optional[bool] = None,
- **kwargs) -> dict:
- # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly
- if attention_mask is None:
- attention_mask = input_ids.new_ones(input_ids.shape)
-
- if past:
- input_ids = input_ids[:, -1:]
- # first step, decoder_cached_states are empty
- return {
- "input_ids": input_ids, # encoder_outputs is defined. input_ids not needed
- "attention_mask": attention_mask,
- "past_key_values": past,
- "use_cache": use_cache,
- }
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/lora.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/lora.py
deleted file mode 100644
index 272601818..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/lora.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import math
-from typing import Optional
-
-import loralib as lora
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-
-class LoraLinear(lora.LoRALayer, nn.Module):
- """Replace in-place ops to out-of-place ops to fit gemini. Convert a torch.nn.Linear to LoraLinear.
- """
-
- def __init__(
- self,
- weight: nn.Parameter,
- bias: Optional[nn.Parameter],
- r: int = 0,
- lora_alpha: int = 1,
- lora_dropout: float = 0.,
- fan_in_fan_out: bool = False, # Set this to True if the layer to replace stores weight like (fan_in, fan_out)
- merge_weights: bool = True,
- ):
- nn.Module.__init__(self)
- lora.LoRALayer.__init__(self,
- r=r,
- lora_alpha=lora_alpha,
- lora_dropout=lora_dropout,
- merge_weights=merge_weights)
- self.weight = weight
- self.bias = bias
-
- out_features, in_features = weight.shape
- self.in_features = in_features
- self.out_features = out_features
-
- self.fan_in_fan_out = fan_in_fan_out
- # Actual trainable parameters
- if r > 0:
- self.lora_A = nn.Parameter(self.weight.new_zeros((r, in_features)))
- self.lora_B = nn.Parameter(self.weight.new_zeros((out_features, r)))
- self.scaling = self.lora_alpha / self.r
- # Freezing the pre-trained weight matrix
- self.weight.requires_grad = False
- self.reset_parameters()
- if fan_in_fan_out:
- self.weight.data = self.weight.data.T
-
- def reset_parameters(self):
- if hasattr(self, 'lora_A'):
- # initialize A the same way as the default for nn.Linear and B to zero
- nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
- nn.init.zeros_(self.lora_B)
-
- def train(self, mode: bool = True):
-
- def T(w):
- return w.T if self.fan_in_fan_out else w
-
- nn.Module.train(self, mode)
- if self.merge_weights and self.merged:
- # Make sure that the weights are not merged
- if self.r > 0:
- self.weight.data -= T(self.lora_B @ self.lora_A) * self.scaling
- self.merged = False
-
- def eval(self):
-
- def T(w):
- return w.T if self.fan_in_fan_out else w
-
- nn.Module.eval(self)
- if self.merge_weights and not self.merged:
- # Merge the weights and mark it
- if self.r > 0:
- self.weight.data += T(self.lora_B @ self.lora_A) * self.scaling
- delattr(self, 'lora_A')
- delattr(self, 'lora_B')
- self.merged = True
-
- def forward(self, x: torch.Tensor):
-
- def T(w):
- return w.T if self.fan_in_fan_out else w
-
- if self.r > 0 and not self.merged:
- result = F.linear(x, T(self.weight), bias=self.bias)
- if self.r > 0:
- result = result + (self.lora_dropout(x) @ self.lora_A.t() @ self.lora_B.t()) * self.scaling
- return result
- else:
- return F.linear(x, T(self.weight), bias=self.bias)
-
-
-def lora_linear_wrapper(linear: nn.Linear, lora_rank: int) -> LoraLinear:
- assert lora_rank <= linear.in_features, f'LoRA rank ({lora_rank}) must be less than or equal to in features ({linear.in_features})'
- lora_linear = LoraLinear(linear.weight, linear.bias, r=lora_rank, merge_weights=False)
- return lora_linear
-
-
-def convert_to_lora_recursively(module: nn.Module, lora_rank: int) -> None:
- for name, child in module.named_children():
- if isinstance(child, nn.Linear):
- setattr(module, name, lora_linear_wrapper(child, lora_rank))
- else:
- convert_to_lora_recursively(child, lora_rank)
-
-
-class LoRAModule(nn.Module):
- """A LoRA module base class. All derived classes should call `convert_to_lora()` at the bottom of `__init__()`.
- This calss will convert all torch.nn.Linear layer to LoraLinear layer.
-
- Args:
- lora_rank (int, optional): LoRA rank. 0 means LoRA is not applied. Defaults to 0.
- lora_train_bias (str, optional): Whether LoRA train biases.
- 'none' means it doesn't train biases. 'all' means it trains all biases. 'lora_only' means it only trains biases of LoRA layers.
- Defaults to 'none'.
- """
-
- def __init__(self, lora_rank: int = 0, lora_train_bias: str = 'none') -> None:
- super().__init__()
- self.lora_rank = lora_rank
- self.lora_train_bias = lora_train_bias
-
- def convert_to_lora(self) -> None:
- if self.lora_rank <= 0:
- return
- convert_to_lora_recursively(self, self.lora_rank)
- lora.mark_only_lora_as_trainable(self, self.lora_train_bias)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/loss.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/loss.py
deleted file mode 100644
index b8b55965b..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/loss.py
+++ /dev/null
@@ -1,117 +0,0 @@
-from typing import Optional
-
-import torch
-import torch.nn as nn
-
-from utils import masked_mean
-
-
-class GPTLMLoss(nn.Module):
- """
- GPT Language Model Loss
- """
-
- def __init__(self):
- super().__init__()
- self.loss = nn.CrossEntropyLoss()
-
- def forward(self, logits: torch.Tensor, labels: torch.Tensor) -> torch.Tensor:
- shift_logits = logits[..., :-1, :].contiguous()
- shift_labels = labels[..., 1:].contiguous()
- # Flatten the tokens
- return self.loss(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
-
-
-class PolicyLoss(nn.Module):
- """
- Policy Loss for PPO
- """
-
- def __init__(self, clip_eps: float = 0.2) -> None:
- super().__init__()
- self.clip_eps = clip_eps
-
- def forward(self,
- log_probs: torch.Tensor,
- old_log_probs: torch.Tensor,
- advantages: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- ratio = (log_probs - old_log_probs).exp()
- surr1 = ratio * advantages
- surr2 = ratio.clamp(1 - self.clip_eps, 1 + self.clip_eps) * advantages
- loss = -torch.min(surr1, surr2)
- if action_mask is not None:
- loss = masked_mean(loss, action_mask)
- loss = loss.mean()
- return loss
-
-
-class ValueLoss(nn.Module):
- """
- Value Loss for PPO
- """
-
- def __init__(self, clip_eps: float = 0.4) -> None:
- super().__init__()
- self.clip_eps = clip_eps
-
- def forward(self,
- values: torch.Tensor,
- old_values: torch.Tensor,
- reward: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- values_clipped = old_values + (values - old_values).clamp(-self.clip_eps, self.clip_eps)
- surr1 = (values_clipped - reward)**2
- surr2 = (values - reward)**2
- loss = torch.max(surr1, surr2)
- loss = loss.mean()
- return loss
-
-
-class PPOPtxActorLoss(nn.Module):
- """
- To Do:
-
- PPO-ptx Actor Loss
- """
-
- def __init__(self, policy_clip_eps: float = 0.2, pretrain_coef: float = 0.0, pretrain_loss_fn=GPTLMLoss()) -> None:
- super().__init__()
- self.pretrain_coef = pretrain_coef
- self.policy_loss_fn = PolicyLoss(clip_eps=policy_clip_eps)
- self.pretrain_loss_fn = pretrain_loss_fn
-
- def forward(self,
- log_probs: torch.Tensor,
- old_log_probs: torch.Tensor,
- advantages: torch.Tensor,
- lm_logits: torch.Tensor,
- lm_input_ids: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- policy_loss = self.policy_loss_fn(log_probs, old_log_probs, advantages, action_mask=action_mask)
- lm_loss = self.pretrain_loss_fn(lm_logits, lm_input_ids)
- return policy_loss + self.pretrain_coef * lm_loss
-
-
-class LogSigLoss(nn.Module):
- """
- Pairwise Loss for Reward Model
- Details: https://arxiv.org/abs/2203.02155
- """
-
- def forward(self, chosen_reward: torch.Tensor, reject_reward: torch.Tensor) -> torch.Tensor:
- probs = torch.sigmoid(chosen_reward - reject_reward)
- log_probs = torch.log(probs)
- loss = -log_probs.mean()
- return loss
-
-
-class LogExpLoss(nn.Module):
- """
- Pairwise Loss for Reward Model
- Details: https://arxiv.org/abs/2204.05862
- """
-
- def forward(self, chosen_reward: torch.Tensor, reject_reward: torch.Tensor) -> torch.Tensor:
- loss = torch.log(1 + torch.exp(reject_reward - chosen_reward)).mean()
- return loss
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/base.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/base.py
deleted file mode 100644
index 0cd1c1fb5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/base.py
+++ /dev/null
@@ -1,136 +0,0 @@
-from abc import ABC, abstractmethod
-from contextlib import nullcontext
-from typing import Any, List, Optional, Tuple, Union
-
-import numpy as np
-import torch
-import torch.nn as nn
-from ..base import LM, Actor, Critic, RewardModel
-from coati.replay_buffer import ReplayBuffer
-from torch.optim import Optimizer
-from torch.utils.data import DataLoader
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .sampler import DistributedSampler
-
-ModelOptimPair = Tuple[nn.Module, Optimizer]
-ModelOrModelOptimPair = Union[nn.Module, ModelOptimPair]
-
-
-class Strategy(ABC):
- """
- Base class for training strategies.
- """
-
- def __init__(self) -> None:
- super().__init__()
- self.setup_distributed()
-
- @abstractmethod
- def backward(self, loss: torch.Tensor, model: nn.Module, optimizer: Optimizer, **kwargs) -> None:
- pass
-
- @abstractmethod
- def optimizer_step(self, optimizer: Optimizer, **kwargs) -> None:
- pass
-
- @abstractmethod
- def setup_distributed(self) -> None:
- pass
-
- @abstractmethod
- def setup_model(self, model: nn.Module) -> nn.Module:
- pass
-
- @abstractmethod
- def setup_optimizer(self, optimizer: Optimizer, model: nn.Module) -> Optimizer:
- pass
-
- @abstractmethod
- def setup_dataloader(self, replay_buffer: ReplayBuffer, pin_memory: bool = False) -> DataLoader:
- pass
-
- def model_init_context(self):
- return nullcontext()
-
- def prepare(
- self, *models_or_model_optim_pairs: ModelOrModelOptimPair
- ) -> Union[List[ModelOrModelOptimPair], ModelOrModelOptimPair]:
- """Prepare models or model-optimizer-pairs based on each strategy.
-
- Example::
- >>> # when fine-tuning actor and critic
- >>> (actor, actor_optim), (critic, critic_optim), reward_model, initial_model = strategy.prepare((actor, actor_optim), (critic, critic_optim), reward_model, initial_model)
- >>> # or when training reward model
- >>> (reward_model, reward_model_optim) = strategy.prepare((reward_model, reward_model_optim))
- >>> # or just inference
- >>> actor, critic = strategy.prepare(actor, critic)
-
- Returns:
- Union[List[ModelOrModelOptimPair], ModelOrModelOptimPair]: Models or model-optimizer-pairs in the original order.
- """
-
- def prepare_model(model: nn.Module):
- if isinstance(model, Actor):
- return Actor(self.setup_model(self._unwrap_model(model)))
- return self.setup_model(self._unwrap_model(model))
-
- rets = []
- for arg in models_or_model_optim_pairs:
- if isinstance(arg, tuple):
- assert len(arg) == 2, f'Expect (model, optimizer) pair, got a tuple with size "{len(arg)}"'
- model, optimizer = arg
- model = prepare_model(model)
- optimizer = self.setup_optimizer(optimizer, self._unwrap_model(model))
- rets.append((model, optimizer))
- elif isinstance(arg, nn.Module):
- rets.append(prepare_model(arg))
- else:
- raise RuntimeError(f'Expect model or (model, optimizer) pair, got {type(arg)}')
-
- if len(rets) == 1:
- return rets[0]
- return rets
-
- @staticmethod
- def _unwrap_model(model: nn.Module) -> nn.Module:
- """Useful for saving state dict. As actor is wrapped by Actor class again in `prepare()`, we should unwrap it before saving.
-
- Args:
- model (nn.Module): an actor or a critic
- """
- if isinstance(model, Actor) or isinstance(model, LM):
- return model.model
- return model
-
- @staticmethod
- def _unwrap_actor(actor: Actor) -> nn.Module:
- """Get `actor.model` from a wrapped (by `prepare()`) actor. Useful for getting original huggingface model.
-
- Args:
- actor (Actor): a wrapped actor
- """
- return Strategy._unwrap_model(actor)
-
- @abstractmethod
- def save_model(self,
- model: nn.Module,
- path: str,
- only_rank0: bool = False,
- tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- pass
-
- @abstractmethod
- def load_model(self, model: nn.Module, path: str, map_location: Any = None, strict: bool = True) -> None:
- pass
-
- @abstractmethod
- def save_optimizer(self, optimizer: Optimizer, path: str, only_rank0: bool = False) -> None:
- pass
-
- @abstractmethod
- def load_optimizer(self, optimizer: Optimizer, path: str, map_location: Any = None) -> None:
- pass
-
- def setup_sampler(self, dataset) -> DistributedSampler:
- return DistributedSampler(dataset, 1, 0)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/naive.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/naive.py
deleted file mode 100644
index 55008bb40..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/naive.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from typing import Any, Optional
-
-import torch
-import torch.nn as nn
-import torch.optim as optim
-from coati.replay_buffer import ReplayBuffer
-from coati.models.base import LM, RewardModel
-from coati.models.lora import LoraLinear
-from torch.optim import Optimizer
-from torch.utils.data import DataLoader
-from transformers.tokenization_utils_base import PreTrainedTokenizerBase
-
-from .base import Strategy
-
-
-class NaiveStrategy(Strategy):
- """
- Strategy for single GPU. No parallelism is used.
- """
-
- def backward(self, loss: torch.Tensor, model: nn.Module, optimizer: optim.Optimizer, **kwargs) -> None:
- loss.backward()
-
- def optimizer_step(self, optimizer: optim.Optimizer, **kwargs) -> None:
- optimizer.step()
-
- def setup_distributed(self) -> None:
- pass
-
- def setup_model(self, model: nn.Module) -> nn.Module:
- return model
-
- def setup_optimizer(self, optimizer: optim.Optimizer, model: nn.Module) -> optim.Optimizer:
- return optimizer
-
- def setup_dataloader(self, replay_buffer: ReplayBuffer, pin_memory: bool = False) -> DataLoader:
- return DataLoader(replay_buffer,
- batch_size=replay_buffer.sample_batch_size,
- shuffle=True,
- drop_last=True,
- pin_memory=pin_memory,
- collate_fn=replay_buffer.collate_fn)
-
- def save_model(self, model: nn.Module, path: str, only_rank0: bool = False, tokenizer: Optional[PreTrainedTokenizerBase] = None) -> None:
- for module in model.modules():
- if isinstance(module, LoraLinear):
- module.merge_weights = True
- module.eval()
-
- if isinstance(model, RewardModel):
- state_dict = model.state_dict()
- torch.save(state_dict, path)
- else:
- try:
- if isinstance(model, LM):
- model = model.model
- model.save_pretrained(path)
- if tokenizer is not None:
- tokenizer.save_pretrained(path)
- except AttributeError:
- state_dict = model.state_dict()
- torch.save(state_dict, path)
-
- def load_model(self, model: nn.Module, path: str, map_location: Any = None, strict: bool = True) -> None:
- unwrapped_model = self._unwrap_model(model)
- state_dict = torch.load(path, map_location=map_location)
- unwrapped_model.load_state_dict(state_dict, strict=strict)
-
- def save_optimizer(self, optimizer: Optimizer, path: str, only_rank0: bool = False) -> None:
- torch.save(optimizer.state_dict(), path)
-
- def load_optimizer(self, optimizer: Optimizer, path: str, map_location: Any = None) -> None:
- state_dict = torch.load(path, map_location=map_location)
- optimizer.load_state_dict(state_dict)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/sampler.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/sampler.py
deleted file mode 100644
index e7ab88cef..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/strategies/sampler.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import math
-
-import numpy as np
-
-
-class DistributedSampler:
-
- def __init__(self, dataset, num_replicas: int, rank: int) -> None:
- self.dataset = dataset
- self.num_replicas = num_replicas
- self.rank = rank
-
- if len(self.dataset) % self.num_replicas != 0:
- self.num_samples = math.ceil(
- (len(self.dataset) - self.num_replicas) / self.num_replicas # type: ignore[arg-type]
- )
- else:
- self.num_samples = math.ceil(len(self.dataset) / self.num_replicas)
-
- self.total_size = self.num_samples * self.num_replicas
-
- indices = list(range(len(self.dataset)))
- indices = indices[:self.total_size]
- assert len(indices) == self.total_size
- # subsample
- indices = indices[self.rank:self.total_size:self.num_replicas]
- assert len(indices) == self.num_samples
- self.indices = indices
-
- def sample(self, batch_size: int) -> list:
- sampled_indices = np.random.choice(self.indices, batch_size, replace=False)
- return [self.dataset[idx] for idx in sampled_indices]
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/utils.py b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/utils.py
deleted file mode 100644
index 5a0a9f8a4..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/ppo/utils.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from typing import Optional, Union
-
-import loralib as lora
-import torch
-import torch.nn as nn
-import torch.nn.functional as F
-
-
-def compute_approx_kl(log_probs: torch.Tensor,
- log_probs_base: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- """
- Compute the approximate KL divergence between two distributions.
- Schulman blog: http://joschu.net/blog/kl-approx.html
-
- Args:
- log_probs: Log probabilities of the new distribution.
- log_probs_base: Log probabilities of the base distribution.
- action_mask: Mask for actions.
- """
-
- log_ratio = log_probs - log_probs_base
- approx_kl = (log_ratio.exp() - 1) - log_ratio
- if action_mask is not None:
- approx_kl = masked_mean(approx_kl, action_mask, dim=1)
- return approx_kl
- approx_kl = approx_kl.mean(dim=1)
- return approx_kl
-
-
-def compute_reward(r: Union[torch.Tensor, float],
- kl_coef: float,
- log_probs: torch.Tensor,
- log_probs_base: torch.Tensor,
- action_mask: Optional[torch.Tensor] = None) -> torch.Tensor:
- if kl_coef <= 0.0:
- return r
- kl = compute_approx_kl(log_probs, log_probs_base, action_mask=action_mask)
- reward = r - kl_coef * kl
- return reward
-
-
-def log_probs_from_logits(logits: torch.Tensor, labels: torch.Tensor) -> torch.Tensor:
- log_probs = F.log_softmax(logits, dim=-1)
- log_probs_labels = log_probs.gather(dim=-1, index=labels.unsqueeze(-1))
- return log_probs_labels.squeeze(-1)
-
-
-def masked_mean(tensor: torch.Tensor, mask: torch.Tensor, dim: int = 1) -> torch.Tensor:
- tensor = tensor * mask
- tensor = tensor.sum(dim=dim)
- mask_sum = mask.sum(dim=dim)
- mean = tensor / (mask_sum + 1e-8)
- return mean
-
-
-def masked_normalize(tensor: torch.Tensor, mask: torch.Tensor, dim: int = 1, eps: float = 1e-8) -> torch.Tensor:
- tensor = tensor * mask
- mean = masked_mean(tensor, mask, dim=dim)
- mean_centered = tensor - mean
- var = masked_mean(mean_centered**2, mask, dim=dim)
- return mean_centered * var.clamp(min=eps).rsqrt()
-
-
-def normalize(tensor: torch.Tensor, dim: int = 0, eps: float = 1e-8) -> torch.Tensor:
- mean = tensor.mean(dim)
- mean_centered = tensor - mean
- var = (mean_centered**2).mean(dim)
- norm = mean_centered * var.clamp(min=eps).rsqrt()
- return norm
-
-
-def convert_to_lora(model: nn.Module,
- input_size: int,
- output_size: int,
- lora_rank: int = 16,
- lora_alpha: int = 1,
- lora_dropout: float = 0.,
- fan_in_fan_out: bool = False,
- merge_weights: bool = True):
- if lora_rank > min(input_size, output_size):
- raise ValueError(f"LoRA rank {lora_rank} must be less or equal than {min(input_size, output_size)}")
-
- for name, module in model.named_modules():
- if isinstance(module, nn.Linear):
- module._modules[name] = lora.Linear(input_size,
- output_size,
- r=lora_rank,
- lora_alpha=lora_alpha,
- lora_dropout=lora_dropout,
- fan_in_fan_out=fan_in_fan_out,
- merge_weights=merge_weights)
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/requirements.txt
deleted file mode 100644
index d3d742806..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/self_hosted/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-loralib
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/textgen/README.md b/commune/modules/bittensor/neurons/text/prompting/miners/textgen/README.md
deleted file mode 100644
index c7b6ee866..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/textgen/README.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# OpenAI Bittensor Miner
-This repository contains a Bittensor Miner that uses OpenAI's GPT-3.5-turbo model as its synapse. The miner connects to the Bittensor network, registers its wallet, and serves the GPT-3.5-turbo model to the network.
-
-## Prerequisites
-
-- Python 3.8+
-- OpenAI Python API (https://github.com/openai/openai)
-
-## Installation
-
-1. Clone the repository
-2. Install the required packages with `pip install -r requirements.txt`
-3. Set your OpenAI API key in the `api_key` argument when running the script
-
-For more configuration options related to the wallet, axon, subtensor, logging, and metagraph, please refer to the Bittensor documentation.
-
-## Example Usage
-
-To run the OpenAI Bittensor Miner with default settings, use the following command:
-
-```
-python3 -m pip install -r neurons/text/prompting/miners/openai/requirements.txt
-python3 neurons/text/prompting/miners/openai/neuron.py --openai.api_key
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--openai.api_key OPENAI.API_KEY] [--openai.suffix OPENAI.SUFFIX] [--openai.max_tokens OPENAI.MAX_TOKENS]
- [--openai.temperature OPENAI.TEMPERATURE] [--openai.top_p OPENAI.TOP_P] [--openai.n OPENAI.N]
- [--openai.presence_penalty OPENAI.PRESENCE_PENALTY] [--openai.frequency_penalty OPENAI.FREQUENCY_PENALTY]
- [--openai.model_name OPENAI.MODEL_NAME] [--netuid NETUID] [--neuron.name NEURON.NAME]
- [--neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH] [--neuron.no_set_weights]
- [--neuron.max_batch_size NEURON.MAX_BATCH_SIZE] [--neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN]
- [--neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]] [--neuron.blacklist.allow_non_registered]
- [--neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE] [--neuron.default_priority NEURON.DEFAULT_PRIORITY]
- [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY] [--wallet.path WALLET.PATH] [--wallet._mock]
- [--wallet.reregister WALLET.REREGISTER] [--axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS]
- [--axon.priority.maxsize AXON.PRIORITY.MAXSIZE] [--axon.port AXON.PORT] [--axon.ip AXON.IP]
- [--axon.external_port AXON.EXTERNAL_PORT] [--axon.external_ip AXON.EXTERNAL_IP] [--axon.max_workers AXON.MAX_WORKERS]
- [--axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS] [--subtensor.network SUBTENSOR.NETWORK]
- [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES]
- [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place]
- [--subtensor.register.verbose] [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda]
- [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--logging.debug] [--logging.trace] [--logging.record_log]
- [--logging.logging_dir LOGGING.LOGGING_DIR] [--metagraph._mock] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --openai.api_key OPENAI.API_KEY
- openai api key
- --openai.suffix OPENAI.SUFFIX
- The suffix that comes after a completion of inserted text.
- --openai.max_tokens OPENAI.MAX_TOKENS
- The maximum number of tokens to generate in the completion.
- --openai.temperature OPENAI.TEMPERATURE
- Sampling temperature to use, between 0 and 2.
- --openai.top_p OPENAI.TOP_P
- Nucleus sampling parameter, top_p probability mass.
- --openai.n OPENAI.N How many completions to generate for each prompt.
- --openai.presence_penalty OPENAI.PRESENCE_PENALTY
- Penalty for tokens based on their presence in the text so far.
- --openai.frequency_penalty OPENAI.FREQUENCY_PENALTY
- Penalty for tokens based on their frequency in the text so far.
- --openai.model_name OPENAI.MODEL_NAME
- OpenAI model to use for completion.
- --netuid NETUID Subnet netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.blocks_per_epoch NEURON.BLOCKS_PER_EPOCH
- Blocks until the miner sets weights on chain
- --neuron.no_set_weights
- If True, the model does not set weights.
- --neuron.max_batch_size NEURON.MAX_BATCH_SIZE
- The maximum batch size for forward requests.
- --neuron.max_sequence_len NEURON.MAX_SEQUENCE_LEN
- The maximum sequence length for forward requests.
- --neuron.blacklist.hotkeys [NEURON.BLACKLIST.HOTKEYS ...]
- To blacklist certain hotkeys
- --neuron.blacklist.allow_non_registered
- If True, the miner will allow non-registered hotkeys to mine.
- --neuron.blacklist.default_stake NEURON.BLACKLIST.DEFAULT_STAKE
- Set default stake for miners.
- --neuron.default_priority NEURON.DEFAULT_PRIORITY
- Set default priority for miners.
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --axon.priority.max_workers AXON.PRIORITY.MAX_WORKERS
- maximum number of threads in thread pool
- --axon.priority.maxsize AXON.PRIORITY.MAXSIZE
- maximum size of tasks in priority queue
- --axon.port AXON.PORT
- The local port this axon endpoint is bound to. i.e. 8091
- --axon.ip AXON.IP The local ip this axon binds to. ie. [::]
- --axon.external_port AXON.EXTERNAL_PORT
- The public port this axon broadcasts to the network. i.e. 8091
- --axon.external_ip AXON.EXTERNAL_IP
- The external ip this axon broadcasts to the network to. ie. [::]
- --axon.max_workers AXON.MAX_WORKERS
- The maximum number connection handler threads working simultaneously on this endpoint. The grpc server distributes
- new worker threads to service requests up to this number.
- --axon.maximum_concurrent_rpcs AXON.MAXIMUM_CONCURRENT_RPCS
- Maximum number of allowed active connections
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) --
- mock (creates a mock connection (for testing)) If this option is set it overloads subtensor.chain_endpoint with an
- entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/textgen/neuron.py b/commune/modules/bittensor/neurons/text/prompting/miners/textgen/neuron.py
deleted file mode 100644
index 967c3ebce..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/textgen/neuron.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import openai
-import argparse
-import bittensor
-from typing import List, Dict
-import os
-import commune as c
-
-class TextgenMiner( bittensor.BasePromptingMiner ):
-
- def __init__( self , config):
- super( TextgenMiner, self ).__init__(config=config)
- self.textgen = c.module('textgen')()
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- pass
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- pass
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
-
- def forward( self, messages: List[Dict[str, str]] ) -> str:
-
- msg = messages[-1]['content']
- timeout = 10
- prompt = f'{msg} \n\n RESPONSE: '
- verbose_limit = 100
- c.print('Prompt: ', prompt[-verbose_limit:], color='yellow')
- resp = self.textgen.talk(prompt, timeout=timeout)
- c.print('Response: ', resp[:verbose_limit], color='green')
- return resp
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/miners/textgen/requirements.txt b/commune/modules/bittensor/neurons/text/prompting/miners/textgen/requirements.txt
deleted file mode 100644
index f0dd0aec5..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/miners/textgen/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-openai
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/validators/constitution/neuron.py b/commune/modules/bittensor/neurons/text/prompting/validators/constitution/neuron.py
deleted file mode 100644
index 3c36300ac..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/validators/constitution/neuron.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import os
-import time
-import json
-import math
-import copy
-import queue
-import torch
-import random
-import bittensor
-import argparse
-import bittensor as bt
-
-from loguru import logger
-from types import SimpleNamespace
-from typing import List, Optional, Tuple, Dict
-
-class neuron:
- @classmethod
- def check_config( cls, config: 'bt.Config' ):
- r""" Checks/validates the config namespace object.
- """
- bt.logging.check_config( config )
- bt.wallet.check_config( config )
- bt.subtensor.check_config( config )
- full_path = os.path.expanduser('{}/{}/{}/netuid{}/{}'.format( config.logging.logging_dir, config.wallet.name, config.wallet.hotkey, config.netuid, config.neuron.name ))
- config.neuron.full_path = os.path.expanduser( full_path )
- if not os.path.exists( config.neuron.full_path ):
- os.makedirs( config.neuron.full_path, exist_ok = True)
-
- @classmethod
- def config ( cls ):
- parser = argparse.ArgumentParser()
- parser.add_argument( '--netuid', type = int, help = 'Prompting network netuid', default = 1 )
- parser.add_argument( '--neuron.name', type = str, help = 'Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name ', default = 'core_prompting_validator')
- parser.add_argument( '--neuron.device', type = str, help = 'Device to run the validator on.', default = "cuda" if torch.cuda.is_available() else "cpu" )
- bt.wallet.add_args( parser )
- bt.subtensor.add_args( parser )
- bt.logging.add_args( parser )
- bt.axon.add_args( parser )
- return bt.config( parser )
-
- def __init__( self ):
- self.config = neuron.config()
- self.check_config( self.config )
- bt.logging( config = self.config, logging_dir = self.config.neuron.full_path )
- print( self.config )
- self.subtensor = bt.subtensor ( config = self.config )
- self.wallet = bt.wallet ( config = self.config )
- self.metagraph = bt.metagraph( netuid = self.config.netuid, network = self.subtensor.network )
- print ('done init')
-
- def train( self ):
- while True:
- uids = torch.tensor( random.sample( self.metagraph.uids.tolist(), 2 ), dtype = torch.int64 )
- A = bittensor.text_prompting( keypair = self.wallet.hotkey, axon = self.metagraph.axons[uids[0]] )
- B = bittensor.text_prompting( keypair = self.wallet.hotkey, axon = self.metagraph.axons[uids[1]] )
- resp_A = A.forward(
- roles = ['user'],
- messages = ['ask me a random question?'],
- timeout = 5,
- )
- resp_B = B.forward(
- roles = ['user'],
- messages = ['ask me a random question?'],
- timeout = 5,
- )
- bittensor.logging.info(str(resp_A))
- bittensor.logging.info(str(resp_B))
-
- if resp_A.is_success and resp_B.is_success:
- bittensor.logging.info('success')
- break
- else:
- bittensor.logging.info('failure')
- continue
-
-
-if __name__ == '__main__':
- bittensor.logging.info( 'neuron().train()' )
- neuron().train()
diff --git a/commune/modules/bittensor/neurons/text/prompting/validators/core/README.md b/commune/modules/bittensor/neurons/text/prompting/validators/core/README.md
deleted file mode 100644
index 50a01bbb2..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/validators/core/README.md
+++ /dev/null
@@ -1,95 +0,0 @@
-# Bittensor Prompting Validator
-This repository the the core validator for the bittensor prompting network.
-
-## Prerequisites
-- Python 3.8+
-- Bittensor
-
-## Installation
-1. Clone the repository
-2. Install the required packages with `pip install -r neurons/text/prompting/validators/core/requirements.txt`
-For more configuration options related to the wallet, axon, subtensor, logging, and metagraph, please refer to the Bittensor documentation.
-
-## Example Usage
-To run the Core Bittensor Prompting Validator with default settings, use the following command:
-
-```
-python3 -m pip install -r neurons/text/prompting/validators/core/requirements.txt
-python3 neurons/text/prompting/validators/core/neuron.py
-```
-
-# Full Usage
-```
-usage: neuron.py [-h] [--netuid NETUID] [--neuron.name NEURON.NAME] [--neuron.reward_model_name NEURON.REWARD_MODEL_NAME] [--neuron.inference_topk NEURON.INFERENCE_TOPK] [--neuron.training_topk NEURON.TRAINING_TOPK]
- [--prompting.model_name PROMPTING.MODEL_NAME] [--prompting.min_tokens PROMPTING.MIN_TOKENS] [--prompting.max_tokens PROMPTING.MAX_TOKENS] [--prompting.temperature PROMPTING.TEMPERATURE]
- [--prompting.top_p PROMPTING.TOP_P] [--prompting.logprobs PROMPTING.LOGPROBS] [--prompting.repetition_penalty PROMPTING.REPETITION_PENALTY] [--wallet.name WALLET.NAME] [--wallet.hotkey WALLET.HOTKEY]
- [--wallet.path WALLET.PATH] [--wallet._mock] [--wallet.reregister WALLET.REREGISTER] [--subtensor.network SUBTENSOR.NETWORK] [--subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT] [--subtensor._mock]
- [--subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES] [--subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL] [--subtensor.register.no_output_in_place] [--subtensor.register.verbose]
- [--subtensor.register.cuda.use_cuda] [--subtensor.register.cuda.no_cuda] [--subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]]
- [--subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB] [--metagraph._mock] [--logging.debug] [--logging.trace] [--logging.record_log] [--logging.logging_dir LOGGING.LOGGING_DIR] [--config CONFIG] [--strict]
-
-optional arguments:
- -h, --help show this help message and exit
- --netuid NETUID Prompting network netuid
- --neuron.name NEURON.NAME
- Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name
- --neuron.reward_model_name NEURON.REWARD_MODEL_NAME
- GPTRewardModel name
- --neuron.inference_topk NEURON.INFERENCE_TOPK
- At inference time, how many miners to we query and return the top rewarded.
- --neuron.training_topk NEURON.TRAINING_TOPK
- During training time, how many miners to we query for each batch based on scores from gating network.
- --prompting.model_name PROMPTING.MODEL_NAME
- Name of the model to use
- --prompting.min_tokens PROMPTING.MIN_TOKENS
- Minimum number of tokens to generate
- --prompting.max_tokens PROMPTING.MAX_TOKENS
- Maximum number of tokens to generate
- --prompting.temperature PROMPTING.TEMPERATURE
- Temperature for sampling
- --prompting.top_p PROMPTING.TOP_P
- Top p for sampling
- --prompting.logprobs PROMPTING.LOGPROBS
- Number of logprobs to return
- --prompting.repetition_penalty PROMPTING.REPETITION_PENALTY
- Repetition penalty for sampling
- --wallet.name WALLET.NAME
- The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)
- --wallet.hotkey WALLET.HOTKEY
- The name of wallet's hotkey.
- --wallet.path WALLET.PATH
- The path to your bittensor wallets
- --wallet._mock To turn on wallet mocking for testing purposes.
- --wallet.reregister WALLET.REREGISTER
- Whether to reregister the wallet if it is not already registered.
- --subtensor.network SUBTENSOR.NETWORK
- The subtensor network flag. The likely choices are: -- finney (main network) -- local (local running network) -- mock (creates a mock connection (for testing)) If this option is set it overloads
- subtensor.chain_endpoint with an entry point node from that network.
- --subtensor.chain_endpoint SUBTENSOR.CHAIN_ENDPOINT
- The subtensor endpoint flag. If set, overrides the --network flag.
- --subtensor._mock To turn on subtensor mocking for testing purposes.
- --subtensor.register.num_processes SUBTENSOR.REGISTER.NUM_PROCESSES, -n SUBTENSOR.REGISTER.NUM_PROCESSES
- Number of processors to use for registration
- --subtensor.register.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --subtensor.register.cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, --cuda.update_interval SUBTENSOR.REGISTER.UPDATE_INTERVAL, -u SUBTENSOR.REGISTER.UPDATE_INTERVAL
- The number of nonces to process before checking for next block during registration
- --subtensor.register.no_output_in_place, --no_output_in_place
- Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.
- --subtensor.register.verbose
- Whether to ouput the registration statistics verbosely.
- --subtensor.register.cuda.use_cuda, --cuda, --cuda.use_cuda
- Set flag to use CUDA to register.
- --subtensor.register.cuda.no_cuda, --no_cuda, --cuda.no_cuda
- Set flag to not use CUDA for registration
- --subtensor.register.cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...], --cuda.dev_id SUBTENSOR.REGISTER.CUDA.DEV_ID [SUBTENSOR.REGISTER.CUDA.DEV_ID ...]
- Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).
- --subtensor.register.cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB, --cuda.TPB SUBTENSOR.REGISTER.CUDA.TPB
- Set the number of Threads Per Block for CUDA.
- --metagraph._mock To turn on metagraph mocking for testing purposes.
- --logging.debug Turn on bittensor debugging information
- --logging.trace Turn on bittensor trace level information
- --logging.record_log Turns on logging to file.
- --logging.logging_dir LOGGING.LOGGING_DIR
- Logging default root directory.
- --config CONFIG If set, defaults are overridden by passed file.
- --strict If flagged, config will check that only exact arguemnts have been set.
-```
\ No newline at end of file
diff --git a/commune/modules/bittensor/neurons/text/prompting/validators/core/gating.py b/commune/modules/bittensor/neurons/text/prompting/validators/core/gating.py
deleted file mode 100644
index 596625819..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/validators/core/gating.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-import argparse
-import bittensor
-from transformers import AutoModel, AutoTokenizer, AutoConfig
-
-class GatingModel( torch.nn.Module ):
- """
- This class is a PyTorch module that encapsulates the gating model functionality.
-
- - The backward method runs a backward pass through the model using the mean squared error between the normalized scores and the normalized rewards as the loss function.
- - The forward method runs a forward pass through the model, encoding the input message and generating scores for each uid in the network. The scores are returned as a tensor.
- """
-
- @classmethod
- def add_args( cls, parser: argparse.ArgumentParser ):
- """
- Adds command line arguments to the parser that are used to configure the gating model.
- The arguments added are:
- - `--gating.model_name`: Name of the pre-trained transformer-based language model to use as the encoding layer for the gating model. (default: 'EleutherAI/gpt-neo-125m')
- - `--gating.num_uids`: Number of uids to gate on. (default: 4096)
- - `--gating.learning_rate`: Learning rate for the gating model optimizer. (default: 0.01)
- - `--gating.momentum`: Momentum for the gating model optimizer. (default: 0.9)
- """
- parser.add_argument('--gating.model_name', type=str, default='EleutherAI/gpt-neo-125m', help='Name of the model to use as the encoding layer for the gating model')
- parser.add_argument('--gating.num_uids', type=int, default=4096, help='Number of uids to gate on')
- parser.add_argument('--gating.learning_rate', type=float, default=0.01, help='Learning rate for the gating model')
- parser.add_argument('--gating.momentum', type=float, default=0.9, help='Momentum for the gating model')
-
- @classmethod
- def config ( cls ):
- """
- Returns a configuration object that contains the command line arguments for the gating model.
- """
- parser = argparse.ArgumentParser()
- cls.add_args( parser )
- return bittensor.config( parser )
-
- @classmethod
- def check_config( cls, config: 'bittensor.Config' ):
- """
- Validates the configuration object for the gating model.
- """
- pass
-
- def __init__(
- self,
- metagraph: 'bittensor.metagraph.Metagraph',
- config: 'bittensor.config' = None,
- model_name: str = None,
- num_uids: int = None
- ):
- """
- Initializes the gating model.
- - `metagraph`: A reference to the Bittensor metagraph object.
- - `config`: Configuration object for the gating model. If `None`, the default configuration is used.
- - `model_name`: Name of the pre-trained transformer-based language model to use as the encoding layer for the gating model. If `None`, the default model name specified in the configuration is used.
- - `num_uids`: Number of uids to gate on. If `None`, the default number specified in the configuration is used.
- """
- super(GatingModel, self).__init__()
- if config is None: config = GatingModel.config()
- if model_name is not None: config.gating.model_name = model_name
- config.gating.num_uids = num_uids if num_uids is not None else metagraph.n
- self.config = config
- self.num_uids = config.gating.num_uids
- self.device = torch.device( self.config.neuron.device )
- self.tokenizer = AutoTokenizer.from_pretrained( self.config.gating.model_name )
- self.model = AutoModel.from_pretrained( self.config.gating.model_name)
- self.linear = torch.nn.Linear( self.model.config.hidden_size, config.gating.num_uids )
- self.optimizer = torch.optim.SGD(
- [ {"params": self.parameters()} ],
- lr = self.config.gating.learning_rate,
- momentum = self.config.gating.momentum,
- )
-
- def backward( self, scores: torch.FloatTensor, rewards: torch.FloatTensor ):
- """ Runs a backward pass through the model.
- Args:
- scores (:obj:`torch.FloatTensor` of shape :obj:`(metagraph.n)`):
- Scores for each uids as output by the gating model.
- rewards (:obj:`torch.FloatTensor` of shape :obj:`(metagraph.n)`):
- Rewards for each uids as output by the reward model.
- """
- normalized_scores = torch.nn.functional.softmax( scores, dim=0 ).to( self.device )
- nomralized_rewards = torch.nn.functional.softmax( rewards, dim=0 ).to( self.device )
- loss = torch.nn.functional.mse_loss( normalized_scores, nomralized_rewards.detach() )
- loss.backward()
- self.optimizer.step()
-
- def forward( self, message: str ) -> 'torch.FloatTensor':
- """ Runs a forward pass through the model.
- Args:
- message (:obj:`str`):
- text message to be encoded.
- Returns:
- scores (:obj:`torch.FloatTensor` of shape :obj:`(network_size)`):
- Scores for each uids as output by the gating model.
- """
- inputs = self.tokenizer( message, return_tensors="pt" ,truncation=True, max_length=2048).to( self.device )
- with torch.no_grad():
- hidden_states = self.model( **inputs ).last_hidden_state[0, -1, :]
- return self.linear( hidden_states )
-
-
diff --git a/commune/modules/bittensor/neurons/text/prompting/validators/core/neuron.py b/commune/modules/bittensor/neurons/text/prompting/validators/core/neuron.py
deleted file mode 100644
index 3b88248c2..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/validators/core/neuron.py
+++ /dev/null
@@ -1,803 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import os
-import time
-import math
-import copy
-import queue
-import torch
-import random
-import bittensor
-import argparse
-import bittensor as bt
-import traceback
-
-from loguru import logger
-from types import SimpleNamespace
-from typing import List, Optional, Tuple, Dict
-from reward import RewardModel
-from gating import GatingModel
-from transformers import AutoTokenizer, AutoModelForSequenceClassification
-from datasets import load_dataset
-from datetime import datetime
-
-__default_question_prompt__ = '''
-Ask me a random question about anything. Make the question very domain specific. Do not include the answer in the question.
-'''
-
-__default_base_prompt__ = '''
-You are designed to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics.
-'''
-
-__default_follow_up_prompt__ = '''
-Ask a follow up question.
-'''
-class neuron:
- @classmethod
- def check_config( cls, config: 'bt.Config' ):
- r""" Checks/validates the config namespace object.
- """
- bt.logging.check_config( config )
- bt.wallet.check_config( config )
- bt.subtensor.check_config( config )
- full_path = os.path.expanduser('{}/{}/{}/netuid{}/{}'.format( config.logging.logging_dir, config.wallet.name, config.wallet.hotkey, config.netuid, config.neuron.name ))
- config.neuron.full_path = os.path.expanduser( full_path )
- config.neuron.reward_path = os.path.expanduser( config.neuron.reward_path )
- if not os.path.exists( config.neuron.full_path ):
- os.makedirs( config.neuron.full_path, exist_ok = True)
- if not os.path.exists( config.neuron.reward_path + '/hf_ckpt.pt' ):
- os.makedirs( config.neuron.reward_path, exist_ok = True )
- os.system(
- f"wget -O { config.neuron.reward_path + '/hf_ckpt.pt'} \
- https://huggingface.co/Dahoas/gptj-rm-static/resolve/main/hf_ckpt.pt"
- )
- if not config.neuron.dont_save_events:
- # Add custom event logger for the events.
- logger.level("EVENTS", no=38, icon="📝")
- logger.add(
- config.neuron.full_path + "/" + "completions.log",
- rotation=config.neuron.events_retention_size, serialize=True, enqueue=True, backtrace=False, diagnose=False, level="EVENTS",
- format = "{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message} | {extra[prompt]} {extra[completion]} {extra[uids]} {extra[all_uids]} {extra[rewards]}{extra[all_completions]} {extra[block]}"
- )
-
- def record_event( self, event: SimpleNamespace ):
- self.history.put( event )
- if not self.config.neuron.dont_save_events:
- logger.log(
- "EVENTS",
- "events",
- prompt = event.message,
- completion = event.completion,
- uids = event.uids.tolist(),
- all_uids = event.all_uids.tolist(),
- rewards = event.rewards.tolist(),
- all_completions = event.all_completions,
- block = event.block.item(),
- )
-
- @classmethod
- def add_args( cls, parser ):
- # Netuid Arg
- parser.add_argument( '--netuid', type = int, help = 'Prompting network netuid', default = 1 )
- parser.add_argument( '--neuron.name', type = str, help = 'Trials for this miner go in miner.root / (wallet_cold - wallet_hot) / miner.name ', default = 'core_prompting_validator')
- parser.add_argument( '--neuron.base_prompt', type=str, help = 'Prompt injected before a question is completed by miners on the network', default = __default_base_prompt__ )
- parser.add_argument( '--neuron.follow_up_prompt', type=str, help = 'Follow up prompt that is completed by miners on the network.', default = __default_follow_up_prompt__ )
- parser.add_argument( '--neuron.reset_bootstrap_prompt_frequency', type=int, help = 'How frequent to use the base follow up question.', default = 3 )
- parser.add_argument( '--neuron.question_prompt', type=str, help = 'Prompt used to generate questions from the network whicha are used to evaluate other miners.', default = __default_question_prompt__ )
- parser.add_argument( '--neuron.reward_model_name', type = str, help = 'GPTRewardModel name', default = 'Dahoas/gpt2-rm-static')
- parser.add_argument( '--neuron.length_timeout_multiplier', type = int, help = 'Base timeout for all requests.', default = 0.01 )
- parser.add_argument( '--neuron.inference_topk', type = int, help = 'At inference time, how many miners to we query and return the top rewarded.', default = 10 )
- parser.add_argument( '--neuron.training_topk', type = int, help = 'During training time, how many miners to we query for each batch based on scores from gating network.', default = 50 )
- parser.add_argument( '--neuron.training_timeout', type = int, help = 'Query timeout during training', default = 4 )
- parser.add_argument( '--neuron.inference_timeout', type = int, help = 'Query timeout during inference', default = 10 )
- parser.add_argument( '--neuron.inference_only', action = 'store_true', help = 'If set, training off and only inference will be served via axon.', default = False )
- parser.add_argument( '--neuron.axon_off', action = 'store_true', help = 'If set, the axon will be turned off.', default = False )
- parser.add_argument( '--neuron.reward_path', type = str, help = 'Path to reward model.', default = '~/.bittensor/reward_models' )
- parser.add_argument( '--neuron.max_history', type = int, help = 'Maximum number history values to store at any time.', default = 100000 )
- parser.add_argument( '--neuron.device', type = str, help = 'Device to run the validator on.', default = "cuda" if torch.cuda.is_available() else "cpu" )
- parser.add_argument( '--neuron.epoch_length_override', type = int, help = 'Override the default timeout', default = -1 )
- parser.add_argument( '--neuron.dont_save_events', action = 'store_true', help = 'If set, we dont save events to a log file.', default = False )
- parser.add_argument( '--neuron.events_retention_size', type = str, help = 'Events retention size.', default = "2 GB" )
- parser.add_argument( '--neuron.no_reward_model', action = 'store_true', help = 'If set, we dont load the reward model instead use just the scores.', default = False )
- parser.add_argument( '--neuron.question_random_sample_uids', action = 'store_true', help = 'If set, random sample uids to get question.', default = False )
- parser.add_argument( '--neuron.reward_shift', type = int, help = 'The value to shift rewards for calculation.', default = 3 )
- parser.add_argument( '--neuron.no_nsfw_filter', action = 'store_true', help = 'If set, allow handling of not-safe-for-work messages.', default = False )
- parser.add_argument( '--neuron.vpermit_tao_limit', type = int, help = 'The maximum number of TAO allowed to query a validator with a vpermit.', default = 1024 )
-
- @classmethod
- def config ( cls ):
- parser = argparse.ArgumentParser()
- bt.wallet.add_args( parser )
- bt.subtensor.add_args( parser )
- bt.logging.add_args( parser )
- bt.axon.add_args( parser )
- GatingModel.add_args( parser )
- cls.add_args( parser )
- return bt.config( parser )
-
- def __init__( self ):
- self.config = neuron.config()
- self.check_config( self.config )
- bt.logging( config = self.config, logging_dir = self.config.neuron.full_path )
- print( self.config )
-
- self.subtensor = bt.subtensor ( config = self.config )
- self.device = torch.device( self.config.neuron.device )
- self.wallet = bt.wallet ( config = self.config )
- self.metagraph = bt.metagraph( netuid = self.config.netuid, network = self.subtensor.network )
- self.wallet.create_if_non_existent()
- self.wallet.reregister( subtensor = self.subtensor, netuid = self.config.netuid )
- self.uid = self.wallet.get_uid( subtensor = self.subtensor, netuid = self.config.netuid )
- self.tokenizer = AutoTokenizer.from_pretrained( 'EleutherAI/gpt-j-6b' )
-
- # check if invoking iter() is indeed necessary
- self.dataset = iter(load_dataset('squad_v2', split='train', streaming=True).shuffle(buffer_size=10000))
-
- self.moving_averaged_scores = torch.zeros((self.metagraph.n)).to( self.device )
- self.alpha = 0.99
- self.hotkeys = self.metagraph.hotkeys
- # Reward model
- if not self.config.neuron.no_reward_model:
- bittensor.logging.info('Loading reward model')
- self.reward_model = RewardModel( model_path = 'EleutherAI/gpt-j-6b', device = self.config.neuron.device )
- for fpath in os.listdir( self.config.neuron.reward_path ):
- if fpath.endswith(".pt") or fpath.endswith(".bin"):
- checkpoint = os.path.join( self.config.neuron.reward_path, fpath )
- break
- ckpt_state = torch.load( checkpoint )
- self.reward_model.load_state_dict( ckpt_state )
- self.reward_model.eval()
- self.reward_model.half()
- self.reward_model.requires_grad_( False )
- self.reward_model.to( self.device )
- bittensor.logging.info('done loading reward model')
-
- # Init the gating model which learns which miners to select for each query.
- self.gating_model = GatingModel( metagraph = self.metagraph, config = self.config ).to( self.device )
- # Denddrite pool for querying the network.
- self.dendrite_pool = bt.text_prompting_pool( keypair = self.wallet.hotkey, metagraph = self.metagraph )
- self.inference_pool = bt.text_prompting_pool( keypair = self.wallet.hotkey, metagraph = self.metagraph )
- # History of forward events.
- self.history = queue.Queue( maxsize = self.config.neuron.max_history )
- # Get a list of peers delegating to me
- delegated = self.subtensor.get_delegated( self.wallet.coldkeypub.ss58_address )
- self.my_nominators = { nomin[0]: nomin[1] for nomin in delegated[0][0].nominators } if len(delegated) else {}
-
- self.load()
- self.check_weights()
-
- # set up filter model
- filter_model_path = 'facebook/roberta-hate-speech-dynabench-r4-target'
- self.filter_model = AutoModelForSequenceClassification.from_pretrained(filter_model_path).to(self.device)
- self.filter_tokenizer = AutoTokenizer.from_pretrained(filter_model_path)
- self.filter_tokenizer.pad_token = self.filter_tokenizer.eos_token
- self.filter_message_count = 0
-
- # Axon set and served for inference requests, unless --neuron.axon_off flag is set.
- if not self.config.neuron.axon_off:
- # Build synapse entrypoint.
- class Synapse( bittensor.TextPromptingSynapse ):
- def priority( _, forward_call: "bittensor.TextPromptingForwardCall" ) -> float:
- if forward_call.src_hotkey == self.wallet.hotkey.ss58_address: return math.inf # myself.
- elif forward_call.src_hotkey in self.my_nominators: return self.my_nominators[ forward_call.src_hotkey ].tao # Delegates.
- else: return 0.0 # Everyone else.
-
- def blacklist( _, forward_call: "bittensor.TextPromptingForwardCall" ) -> bool:
- if forward_call.src_hotkey == self.wallet.hotkey.ss58_address:
- return True
-
- elif forward_call.src_hotkey in self.metagraph.hotkeys:
- uid = self.metagraph.hotkeys.index(forward_call.src_hotkey)
- if self.metagraph.validator_permit[uid]:
- return True
- return False # Non Validator miners
-
- elif forward_call.src_hotkey in self.my_nominators:
- return False # Delegates, dont blacklist.
- else:
- return False # Everyone else, dont blacklist.
-
- def backward( self, messages: List[Dict[str, str]], response: str, rewards: torch.FloatTensor ) -> str: pass
-
- def forward( _, messages: List[Dict[str, str]] ) -> str:
- return self.inference(
- messages = messages,
- timeout = self.config.neuron.inference_timeout
- )
-
- def multi_forward( _, messages: List[Dict[str, str]] ) -> str:
- return self.inference(
- messages = messages,
- timeout = self.config.neuron.inference_timeout,
- return_all = True
- )
-
- # Serve axon.
- self.axon = bittensor.axon(
- wallet = self.wallet,
- metagraph = self.metagraph,
- config = self.config,
- )
- self.synapse = Synapse( axon = self.axon )
- self.axon.start()
- self.subtensor.serve_axon( self.config.netuid, self.axon )
-
- def filter_message(
- self,
- message
- ) -> bool:
- """ Check if the message is related to any sexual content.
-
- Args:
- message (str):
- The message that we check if we should filter out.
- Returns:
- result (bool):
- True indicates we should filter out the result, false indicates the result is safe.
- """
- # If no filter needed, then just return false withough checking.
- if self.config.neuron.no_nsfw_filter:
- return False
-
- now = datetime.now()
- dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
- tokenized = self.filter_tokenizer(message)
- input_ids = tokenized['input_ids']
- bound_score1 = 0.5
- bound_score2 = 0.5
-
- while len(input_ids) > 0:
- _input_ids = input_ids[:512]
-
- with torch.no_grad():
- output = self.filter_model(torch.tensor([_input_ids]).to(self.device))
-
- filter_out = output.logits[0, 0] < bound_score1 or output.logits[0, 1] > bound_score2
-
- if filter_out:
- bittensor.logging.debug( 'filtered message', message )
- break
- else:
- bittensor.logging.debug( 'safe message', message )
-
- input_ids = input_ids[512:]
-
- self.filter_message_count += 1
- return filter_out
-
- def forward(
- self,
- roles: List[ str ],
- messages: List[ str ],
- topk: Optional[int] = None,
- random_sample_uids: Optional[ bool ] = False,
- train_gating_model: Optional[ bool ] = False,
- train_network: Optional[ bool ] = False,
- timeout: float = None,
- question: bool = False,
- ) -> SimpleNamespace:
- """
- Queries the network for a response to the passed message using a gating model to select the best uids.
- Trains the gating model based on the rewards calculated for the successful completions and passes rewards
- backward for potential PPO.
-
- Args:
- roles ( List[ str ] ):
- roles associated with messages.
- message ( List[ str ] ):
- messages content for each role.
- topk (Optional[int]):
- The number of uids to consider for the query. If None or -1, all uids will be considered.
- If provided, selects the top k uids based on the gating model scores.
- random_sample_uids( bool, default = False ):
- If True, randomly samples the uids to query rather than using topk.
- train_gating_model ( bool, default = False ):
- If True, trains the gating model based on the rewards calculated for the successful completions.
- train_network ( bool, default = False ):
- If True, sends backward messages to the network.
- Returns:
- result (SimpleNamespace):
- A namespace containing the completion with the highest reward, message, uids,
- rewards, scores, and all completions.
- """
- bittensor.logging.info( 'forward()' )
- bittensor.logging.debug( 'roles', roles )
- bittensor.logging.debug( 'message', messages )
-
- # Format the messages for the query.
- unravelled_message = ''
- for role, message in list(zip( roles, messages )):
- if role == 'system': unravelled_message += 'system: ' + message + '\n'
- if role== 'assistant': unravelled_message += 'assistant: ' + message + '\n'
- if role == 'user': unravelled_message += 'user: ' + message + '\n'
-
- # Set `topk` to the number of items in `self.metagraph.n` if `topk` is not provided or is -1.
- # Find the available `uids` that are currently serving.
- # If `topk` is larger than the number of available `uids`, set `topk` to the number of available `uids`.
- # Check if we have vpermit and if we do, ensure query only UIDs with less than vpermit_tao_limit.
- def available( uid ) -> bool:
- # Filter non serving axons.
- if not self.metagraph.axons[uid].is_serving:
- return False
- # Filter validator permit > 1024 stake.
- if self.metagraph.validator_permit[uid]:
- if self.metagraph.S[uid] > self.config.neuron.vpermit_tao_limit:
- return False
- # Available otherwise.
- return True
- candidate_uids = [uid for uid, ax in enumerate(self.metagraph.axons) if available( uid )]
- available_uids = torch.tensor( candidate_uids, dtype = torch.int64 ).to( self.device )
- if topk is None or topk == -1: topk = self.metagraph.n.item()
- if topk > len( available_uids ): topk = len( available_uids )
- if len( available_uids ) == 0: bittensor.logging.error( 'no available uids' ); return None
- bittensor.logging.trace( 'available_uids', available_uids )
- bittensor.logging.trace( 'topk', topk )
-
- # We run the gating network here to get the best uids
- # Use the gating model to generate scores for each `uid`.
- scores = self.gating_model( unravelled_message ).to( self.device )
- bittensor.logging.trace( 'scores', scores )
-
- # Select the top `topk` `uids` based on the highest `scores`.
- # Use the selected `uids` to query the dendrite pool.
- # Print the `completions`.
- if random_sample_uids:
- topk_uids = torch.tensor( random.sample( available_uids.tolist(), topk ), dtype = torch.int64 ).to( self.device )
- else:
- topk_uids = available_uids[ scores[ available_uids ].sort()[ 1 ][ -topk: ]]
- forward_calls = self.dendrite_pool(
- roles = roles,
- messages = messages,
- uids = topk_uids,
- timeout = timeout,
- )
- bittensor.logging.trace( 'topk_uids', topk_uids )
-
- # Filter out any `None` `completions`.
- successful_uids = torch.tensor([uid for uid, call in list(zip(topk_uids, forward_calls)) if call is not None and call.completion is not None and len(call.completion)>10], dtype=torch.int64).to(self.device)
- successful_completions = [call.completion for call in forward_calls if call is not None and call.completion is not None and len(call.completion)>10]
- unsuccessful_uids = torch.tensor([uid for uid in topk_uids if uid not in successful_uids])
- bittensor.logging.debug( 'successful_uids', successful_uids )
- if len( successful_completions ) == 0: bittensor.logging.error('no successful completions'); return None
-
- # Calculate the rewards for the successful `completions` using the reward model.
- # Print the rewards for all `uids`.`
- flattened_message_for_reward = ''
- if not self.config.neuron.no_reward_model:
- for role_i, message_i in list(zip(roles, messages)):
- if role_i != 'system': flattened_message_for_reward += message_i.strip() + '\n'
- full_completions_for_reward = [ 'Question: ' + flattened_message_for_reward + 'Answer: ' + comp.strip() for comp in successful_completions ]
- completions_for_reward = [comp.strip() for comp in successful_completions]
- rewards = self.reward_model.reward( full_completions_for_reward, completions_for_reward, difference = True, shift = self.config.neuron.reward_shift).detach().to( self.device )
- bittensor.logging.trace( 'rewards', rewards )
- else:
- rewards = scores[ successful_uids ]
-
- # Train the gating model using the scores and rewards of the successful `completions`.
- if train_gating_model:
- self.gating_model.backward( scores = scores[ successful_uids ], rewards = rewards )
- bittensor.logging.trace( 'Apply backward to gating model' )
-
- # Pass rewards backward for potential PPO.
- if train_network:
- self.dendrite_pool.backward(
- forward_calls = forward_calls,
- rewards = rewards,
- timeout = timeout,
- )
- bittensor.logging.trace( 'Applied backward to network.' )
-
- best_idx = rewards.detach().argmax()
- bittensor.logging.trace( 'rewards', rewards )
- bittensor.logging.trace('successful_completions', len(successful_completions))
- bittensor.logging.trace('best_idx', best_idx)
- best_completion = successful_completions[best_idx]
-
-
- # Save the query history in a `result` object.
- # Return the `completion` with the highest reward.
- event = SimpleNamespace(
- completion = successful_completions[ rewards.argmax( dim = 0 ) ],
- message = message,
- uids = successful_uids,
- rewards = rewards,
- all_uids = topk_uids,
- all_completions = successful_completions,
- block = self.metagraph.block,
- is_question = message == self.config.neuron.question_prompt,
- best_completion = best_completion
- )
- self.record_event( event )
-
- # First we normalize the rewards with a softmax.
- normalized_rewards = torch.nn.functional.softmax( event.rewards.to( self.device ), dim=0 )
-
- # We scatter the normalized onto the moving scores (updating them but not changing the source)
- scattered_rewards = self.moving_averaged_scores.scatter(0, event.uids.to( self.device ), normalized_rewards.to( self.device ) )
- scattered_rewards = scattered_rewards.scatter(0, unsuccessful_uids.to( self.device ) , torch.zeros_like(unsuccessful_uids, dtype=torch.float).to( self.device ) )
-
- # We now perform a moving average of the scattered rewards.
- self.moving_averaged_scores = self.alpha * self.moving_averaged_scores + ( 1 - self.alpha ) * scattered_rewards
- bittensor.logging.trace( 'normalized_rewards', normalized_rewards )
- bittensor.logging.trace( 'scattered_rewards', scattered_rewards )
- bittensor.logging.trace( 'moving_averaged_scores', self.moving_averaged_scores )
- print("===== Best Completion =====")
- print(f"\n===== {successful_uids[best_idx], rewards[best_idx]} =====\n")
-
- print('flattened_message_for_reward:\n', flattened_message_for_reward)
- print('completion:\n', best_completion.strip())
-
- return event
-
- def inference(
- self,
- messages: List[Dict[str, str]],
- timeout: float,
- dont_use_reward_model: bool = True,
- return_all = False
- ) -> str:
- bittensor.logging.info( 'inference()')
-
- # Pre-process messages.
- roles = []; contents = []; unravelled_message = ''; user_message = None
- for message_dict in messages:
- roles.append( message_dict['role'] )
- contents.append( message_dict['content'] )
- if message_dict['role'] == 'system': unravelled_message += 'system: ' + message_dict['content'] + '\n'
- if message_dict['role'] == 'assistant': unravelled_message += 'assistant: ' + message_dict['content'] + '\n'
- if message_dict['role'] == 'user':
- unravelled_message += 'user: ' + message_dict['content'] + '\n'
- user_message = message_dict['content']
-
- bittensor.logging.info( 'inference message', str(unravelled_message) )
-
- if user_message and self.filter_message(user_message):
- if return_all:
- return ['Received possible explicit content.']
- else:
- return 'Received possible explicit content.'
-
- # Get scores for query.
- scores = self.gating_model( unravelled_message ).to( self.device )
- bittensor.logging.info( 'inference scores', str(scores) )
-
- # Get uids for query.
- uids = scores.sort()[ 1 ][ -self.config.neuron.inference_topk: ]
- bittensor.logging.info( 'inference uids', str(uids) )
-
- # Query using dendrite pool
- forward_start = time.time()
- bittensor.logging.trace( 'applying dendrite forward' )
- forward_calls = self.inference_pool(
- roles = roles,
- messages = contents,
- uids = uids,
- timeout = timeout,
- )
- bittensor.logging.trace( 'finished dendrite forward ', time.time() - forward_start )
-
- # Return longest completion.
- if dont_use_reward_model or self.config.neuron.no_reward_model:
- bittensor.logging.info('not applying the reward model taking the best completed response')
- # Return first best from scores.
- forward_calls.reverse()
-
- if return_all:
- completions = []
- for call in forward_calls:
- if len( call.completion ) > 0 and not self.filter_message(call.completion):
- completions.append(call.completion)
- if len(completions) > 0:
- return completions
-
- else:
- for call in forward_calls:
- if len( call.completion ) > 0 and not self.filter_message(call.completion):
- bittensor.logging.info( 'best completion', call.completion )
- return call.completion
-
- if return_all:
- return ['no valid completions']
-
- else:
- return 'no valid completions'
-
-
- else:
- # Format messages for reward model.
- flattened_message_for_reward = ''
- for role_i, message_i in list(zip(roles, messages)):
- if role_i != 'system': flattened_message_for_reward += message_i.strip() + '\n\n'
- completions = [ call.completion for call in forward_calls if len(call.completion) > 0 and not self.filter_message(call.completion) ]
- flattened_completions_for_reward = [ flattened_message_for_reward + comp.strip() for comp in completions ]
-
- # Return best via reward model.
- reward_model_start = time.time()
- completions_for_reward = [comp.strip() for comp in completions]
- rewards = self.reward_model.reward( flattened_completions_for_reward, completions_for_reward, difference =False ).to( self.device )
- best_completion = completions[ rewards.argmax( dim = 0 ) ]
- bittensor.logging.info('finished applying the reward model ', time.time() - reward_model_start )
-
- if return_all:
- return completions
- else:
- return best_completion
-
- def get_question(self, uids, bootstrap_prompt, reset_bootstrap_prompt = False, random_sample_uids = False):
-
- def _get_question(uids, bootstrap_prompt, reset_bootstrap_prompt = False):
- # retrieve the answer
- # sample = next(self.dataset)
- # google_ai_dataset_place_holder = sample['answers']['text'][0]
-
- if reset_bootstrap_prompt:
- bootstrap_prompt = next(self.dataset)['context'] # google_ai_dataset_place_holder
- self.base_prompt = bootstrap_prompt
- with open('prompt_history.txt', 'a') as file:
- file.write("============== reset ==================" + '\n')
- file.write(f"bootstrap prompt: {bootstrap_prompt}" + '\n')
-
- else:
- bootstrap_prompt = bootstrap_prompt.replace('As an AI language model, ', '')
-
- question_prompt = f"{bootstrap_prompt}\n\n{self.config.neuron.follow_up_prompt}"
-
- questions = self.dendrite_pool(
- roles = ['user'],
- messages = [ question_prompt ],
- uids = uids,
- timeout = 12,
- )
-
- successful_questions = [question.completion for question in questions if question is not None and question.completion is not None and len(question.completion) > 10 and not self.filter_message(question.completion) ]
- full_completions_for_reward = [ 'Question: ' + bootstrap_prompt + 'Answer: ' + comp.strip() for comp in successful_questions ]
- completions_for_reward = [comp.strip() for comp in successful_questions]
- reward_diffs = torch.zeros(len(successful_questions))
- if not self.config.neuron.no_reward_model:
- reward_diffs = self.reward_model.reward( full_completions_for_reward, completions_for_reward, difference = True, shift = self.config.neuron.reward_shift ).to( self.device )
- for question, reward_diff in zip(successful_questions, reward_diffs.tolist()):
- print(f"\n=== Question score: {reward_diff}===\n")
- print(question)
- if reward_diff > 0 :
- return question, reward_diff
-
- return None, None
-
- def _get_random_uids():
- available_uids = torch.tensor( [ uid for uid, ax in enumerate( self.metagraph.axons ) if ax.is_serving ], dtype = torch.int64 )
- uids = torch.tensor( random.sample( available_uids.tolist(), self.config.neuron.training_topk ), dtype = torch.int64 )
- return uids
-
- question = None
-
- if random_sample_uids:
- uids = _get_random_uids()
-
- while question is None:
- question, reward_diff = _get_question(uids, bootstrap_prompt, reset_bootstrap_prompt)
- reset_bootstrap_prompt = True
- uids = _get_random_uids()
-
- return question, reward_diff
-
- def train( self ):
- """ Training
- The function uses an infinite loop to repeatedly generate a random question,
- ask the network to complete the question, and train the gating network using
- the question and the resulting completions.
- """
- # Store the current epoch block number for comparison later.
- last_epoch_block = self.subtensor.block
- steps = 0
-
- # grab the question from the current sample
- prompt = next(self.dataset)['context']
- self.base_prompt = self.config.neuron.base_prompt
- reward_diff = 0
- self.last_sync = self.subtensor.block
-
- # Start an infinite loop for training.
- try:
- while True:
- # Ask the network to complete the random question, training the gating network.
- with open('prompt_history.txt', 'a') as file:
- file.write(f"{steps} | Q score({round(reward_diff , 4)}): {prompt}" + '\n')
-
- forward_result = self.forward(
- roles = ['system', 'user' ],
- messages = [ self.base_prompt, prompt ],
- topk = self.config.neuron.training_topk,
- random_sample_uids = True,
- train_gating_model = True,
- timeout = self.config.neuron.inference_timeout,
- question = False
- )
-
- if forward_result is not None:
- with open('prompt_history.txt', 'a') as file:
- file.write(f"{steps} | A score({round(forward_result.rewards.sort(descending = True)[0][0].item(), 4)}): {forward_result.best_completion}" + '\n')
-
- idx_reward_sorted = forward_result.rewards.sort(descending = True)[1]
- prompt, reward_diff = self.get_question(
- uids = forward_result.uids[idx_reward_sorted],
- bootstrap_prompt = forward_result.best_completion,
- reset_bootstrap_prompt = (steps % self.config.neuron.reset_bootstrap_prompt_frequency == 0),
- random_sample_uids = self.config.neuron.question_random_sample_uids
- )
-
- # Resync metagraph before returning. (sync every 15 min or ~75 blocks)
- if self.subtensor.block - self.last_sync > 100:
- self.metagraph.sync()
- self.last_sync = self.subtensor.block
- self.save()
- delegates = self.subtensor.get_delegated( self.wallet.coldkeypub.ss58_address )
-
- # Recreate pools here to ensure sizing is correct.
- self.dendrite_pool = bt.text_prompting_pool( keypair = self.wallet.hotkey, metagraph = self.metagraph )
- self.inference_pool = bt.text_prompting_pool( keypair = self.wallet.hotkey, metagraph = self.metagraph )
-
- self.my_nominators = { nomin[0]: nomin[1] for nomin in delegates[0][0].nominators } if len(delegates) else {}
- self.check_weights()
-
- if self.metagraph.n > self.gating_model.num_uids:
- self.gating_model = GatingModel( metagraph = self.metagraph, config = self.config ).to( self.device )
-
- # Check if enough epoch blocks have elapsed since the last epoch.
- epoch_length = self.subtensor.validator_epoch_length(self.config.netuid) if self.config.neuron.epoch_length_override == -1 else self.config.neuron.epoch_length_override
- blocks_until_epoch = epoch_length - ( self.subtensor.block - last_epoch_block )
- bittensor.logging.debug( 'blocks_until_epoch', blocks_until_epoch )
- if blocks_until_epoch <= 0:
- bittensor.logging.trace( 'epoch()' )
- bittensor.logging.info( 'block', self.subtensor.block )
-
- # Update the last epoch block to the current epoch block.
- last_epoch_block = self.subtensor.block
-
- # Computes the average reward for each uid across non-zero values
- # using the rewards history stored in the self.history list.
- uids, weights = self.compute_weights()
- bittensor.logging.info( 'weights', weights )
-
- # Set the weights on chain via our subtensor connection.
- self.subtensor.set_weights(
- wallet = self.wallet,
- netuid = self.config.netuid,
- uids = uids,
- weights = weights,
- wait_for_finalization = False,
- )
- steps += 1
-
- except Exception as e:
- bittensor.logging.info( 'Error in training loop', str( e ) )
- print(traceback.format_exc())
-
- def compute_weights( self ) -> Tuple[ torch.LongTensor, torch.FloatTensor ]:
- """
- Computes the average reward for each uid across non-zero values
- using the rewards history stored in the self.history list.
-
- Returns:
- uids ( torch.LongTensor, shape = (n) ):
- Uid to set weights on.
- weights ( torch.FloatTensor, shape = (n) ):
- The weights for each uid.
- """
- bittensor.logging.info( 'compute_weights()' )
-
- # Return zeros weights if there is no history.
- if self.history.qsize() == 0:
- bittensor.logging.warning( 'No history to compute weights returning all ones.' )
- return torch.ones((self.metagraph.n)) / self.metagraph.n
-
- # Calculate the average reward for each uid across non-zero values.
- # Replace any NaN values with 0.
- raw_weights = torch.nn.functional.normalize( self.moving_averaged_scores, p=1, dim=0 )
- bittensor.logging.trace( 'raw_weights', raw_weights )
- bittensor.logging.trace( 'top10 values', raw_weights.sort()[0] )
- bittensor.logging.trace( 'top10 uids', raw_weights.sort()[1] )
-
- # Process the raw weights to final_weights via subtensor limitations.
- processed_weight_uids, processed_weights = bittensor.utils.weight_utils.process_weights_for_netuid(
- uids = self.metagraph.uids.to( "cpu" ),
- weights = raw_weights.to( "cpu" ),
- netuid = self.config.netuid,
- subtensor = self.subtensor,
- metagraph = self.metagraph
- )
- bittensor.logging.trace( 'processed_weights', processed_weights )
- bittensor.logging.trace( 'processed_weight_uids', processed_weight_uids )
- return processed_weight_uids, processed_weights
-
- def run(self):
- if self.config.neuron.inference_only:
- # Start an infinite loop, allows axon to service inference requests.
- last_sync = self.subtensor.block
- while True:
- time.sleep(12)
- if self.subtensor.block -last_sync > 100:
- self.metagraph.sync()
- self.last_sync = self.subtensor.block
- self.load(inference_only = True)
-
- else:
- # Normal validator train operation for validation.
- self.train()
-
- def save(self, path=None):
- r""" Save hotkeys and moving average scores to filesystem. """
- try:
- if path is None:
- path = self.config.neuron.full_path
- state_dict = {
- 'neuron_weights': self.moving_averaged_scores,
- 'neuron_hotkeys': self.hotkeys
- }
-
- torch.save(state_dict, f'{path}/model.torch')
- bittensor.logging.success(prefix='Saved model', sufix=f'{path}/model.torch')
-
- gating_state_dict = {
- 'model_state_dict':self.gating_model.state_dict(),
- 'num_hotkeys': self.gating_model.num_uids
- }
- torch.save(gating_state_dict, f'{path}/gating.torch')
- bittensor.logging.success(prefix='Saved gating model', sufix=f'{path}/gating.torch')
- except Exception as e:
- logger.warning(f'Failed to save model with error: {e}')
-
- def load(self, path=None, inference_only=False):
- r""" Load hotkeys and moving average scores from filesystem. """
- try:
- if path is None:
- path = self.config.neuron.full_path
- state_dict = torch.load(f'{path}/model.torch')
- self.moving_averaged_scores = state_dict['neuron_weights'].clone().detach()
- self.hotkeys = state_dict['neuron_hotkeys']
- bittensor.logging.success(prefix='Reloaded model', sufix=f'{path}/model.torch')
-
- gating_state_dict = torch.load(f'{path}/gating.torch')
- if self.gating_model.num_uids == gating_state_dict['num_hotkeys']:
- self.gating_model.load_state_dict(gating_state_dict['model_state_dict'], strict=False)
- bittensor.logging.success(prefix='Reloaded Gating model', sufix=f'{path}/gating.torch')
-
- elif inference_only:
- self.gating_model = GatingModel( metagraph = self.metagraph, config = self.config, num_uids=gating_state_dict['num_hotkeys']).to( self.device )
- self.gating_model.load_state_dict(gating_state_dict['model_state_dict'], strict=False)
- bittensor.logging.success(prefix='Reloaded Gating model', sufix=f'{path}/gating.torch')
-
- except Exception as e:
- logger.warning(f'Failed to load model with error: {e}')
-
- def check_weights(self):
- """ Checks current hotkeys with the current version of the metagraph """
- for uid, hotkey in enumerate( self.hotkeys ):
- if hotkey != self.metagraph.hotkeys[ uid ]:
- self.moving_averaged_scores[ uid ] = 0 #hotkey has been replaced
- if self.metagraph.validator_permit[ uid ] and self.metagraph.S[ uid ] > self.config.neuron.vpermit_tao_limit:
- self.moving_averaged_scores[ uid ] = 0 # hotkey has validation rights and is below the tao limit
- if len(self.hotkeys) < len(self.metagraph.hotkeys):
- new_moving_average = torch.zeros((self.metagraph.n)).to( self.device )
- new_moving_average[:len(self.hotkeys)] = self.moving_averaged_scores
- self.moving_averaged_scores = new_moving_average
- self.hotkeys = copy.deepcopy(self.metagraph.hotkeys)
-
-
-if __name__ == '__main__':
- bittensor.logging.info( 'neuron().train()' )
- neuron().run()
diff --git a/commune/modules/bittensor/neurons/text/prompting/validators/core/reward.py b/commune/modules/bittensor/neurons/text/prompting/validators/core/reward.py
deleted file mode 100644
index 95c5a7f77..000000000
--- a/commune/modules/bittensor/neurons/text/prompting/validators/core/reward.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-#### NOTE(carro): This code is modified from trlX
-
-import torch
-import argparse
-import bittensor
-
-from torch import nn
-from typing import List
-from transformers import AutoModelForCausalLM, AutoTokenizer, AutoConfig
-
-class RewardModel(nn.Module):
-
- def __init__( self, model_path: str, device: str, config: 'bittensor.config' = None):
- super().__init__()
- config = AutoConfig.from_pretrained( model_path )
- self.model = AutoModelForCausalLM.from_config( config )
- self.config = self.model.config
- # `gpt-neo(x)` models use `hidden_size` attribute names instead of `n_embd``
- if config is None: config = RewardModel.config()
-
- self.config.n_embd = self.config.hidden_size if hasattr(self.config, "hidden_size") else self.config.n_embd
- self.device = torch.device( device )
- self.transformer = self.model.transformer
- self.v_head = nn.Linear(self.config.n_embd, 1, bias=False)
- self.tokenizer = AutoTokenizer.from_pretrained('EleutherAI/gpt-j-6b')
- self.tokenizer.pad_token = self.tokenizer.eos_token
- self.PAD_ID = self.tokenizer(self.tokenizer.pad_token)["input_ids"][0]
-
- def reward( self, full_completions: List[str], comp: List[str], difference=False, shift =3) -> torch.FloatTensor:
- def reward_fn( samples ):
- if samples is None: return 0
- scores_list = []
- batch_size = 1
- for i in range(0, len(samples), batch_size):
- sub_samples = samples[i : i + batch_size]
- sub_samples = [
- "<|startoftext|>" + chosen + "<|endoftext|>" for chosen in sub_samples
- ]
- encodings_dict = self.tokenizer(
- sub_samples,
- truncation=False,
- max_length=550,
- padding="max_length",
- return_tensors="pt",
- )
- input_ids = encodings_dict["input_ids"].to( self.device )
- attn_masks = encodings_dict["attention_mask"].to( self.device )
- input_ids = input_ids.repeat(2, 1)
- attn_masks = attn_masks.repeat(2, 1)
- with torch.no_grad():
- sub_scores = self.forward(input_ids=input_ids.to( self.device ), attention_mask=attn_masks.to( self.device ))
- scores_list.append(sub_scores["chosen_end_scores"])
- scores = torch.cat(scores_list, dim=0).mean().item()
- return scores
-
- with torch.no_grad():
- full_rewards = [reward_fn([completion]) for completion in full_completions]
- if difference:
- comp_rewards = [reward_fn([completion]) for completion in comp]
- return torch.nn.functional.relu(torch.tensor(full_rewards, dtype=torch.float32)+shift) - torch.nn.functional.relu(torch.tensor(comp_rewards, dtype=torch.float32)+shift)
- else:
- for completion, f_reward in zip(full_completions, full_rewards):
- print(completion)
- print(f_reward)
- return torch.tensor(full_rewards, dtype=torch.float32)
- def forward(
- self,
- input_ids=None,
- past_key_values=None,
- attention_mask=None,
- token_type_ids=None,
- position_ids=None,
- head_mask=None,
- inputs_embeds=None,
- mc_token_ids=None,
- labels=None,
- return_dict=False,
- output_attentions=False,
- output_hidden_states=False,
- ):
- loss = None
- transformer_outputs = self.transformer(
- input_ids,
- attention_mask=attention_mask,
- )
-
- hidden_states = transformer_outputs[0]
-
- rewards = self.v_head(hidden_states).squeeze(-1)
- chosen_end_scores = []
- rejected_end_scores = []
-
- # Split the inputs and rewards into two parts, chosen and rejected
- assert len(input_ids.shape) == 2
- bs = input_ids.shape[0] // 2
- chosen = input_ids[:bs]
- rejected = input_ids[bs:]
- chosen_rewards = rewards[:bs]
- rejected_rewards = rewards[bs:]
-
- loss = 0
- inference = False
- for i in range(bs):
- if torch.all(torch.eq(chosen[i], rejected[i])).item():
- c_inds = (chosen[i] == self.PAD_ID).nonzero()
- c_ind = c_inds[0].item() if len(c_inds) > 0 else chosen.shape[1]
- chosen_end_scores.append(chosen_rewards[i, c_ind - 1])
- inference = True
- continue
-
- # Check if there is any padding otherwise take length of sequence
- c_inds = (chosen[i] == self.PAD_ID).nonzero()
- c_ind = c_inds[0].item() if len(c_inds) > 0 else chosen.shape[1]
- r_inds = (rejected[i] == self.PAD_ID).nonzero()
- r_ind = r_inds[0].item() if len(r_inds) > 0 else rejected.shape[1]
- end_ind = max(c_ind, r_ind)
-
- # Retrieve first index where trajectories diverge
- divergence_ind = (chosen[i] != rejected[i]).nonzero()[0]
- assert divergence_ind > 0
-
- # Index into the correct rewards
- c_truncated_reward = chosen_rewards[i][divergence_ind:end_ind]
- r_truncated_reward = rejected_rewards[i][divergence_ind:end_ind]
-
- # Append the last rewards to the list of end scores
- chosen_end_scores.append(c_truncated_reward[-1])
- rejected_end_scores.append(r_truncated_reward[-1])
-
- # Compute loss based on truncated rewards (ignore padding)
- loss += -torch.log(torch.sigmoid(c_truncated_reward - r_truncated_reward)).mean()
- loss = loss / bs
-
- if not inference:
- chosen_end_scores = torch.stack(chosen_end_scores)
- rejected_end_scores = torch.stack(rejected_end_scores)
-
- if inference:
- chosen_end_scores = torch.stack(chosen_end_scores)
- return {"chosen_end_scores": chosen_end_scores}
-
- return {
- "loss": loss,
- "chosen_end_scores": chosen_end_scores,
- "rejected_end_scores": rejected_end_scores,
- }
diff --git a/commune/modules/bittensor/receptor/__init__.py b/commune/modules/bittensor/receptor/__init__.py
deleted file mode 100644
index 98ebd55ec..000000000
--- a/commune/modules/bittensor/receptor/__init__.py
+++ /dev/null
@@ -1,100 +0,0 @@
-""" Factory class for managing grpc connections with axon endpoint
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-from concurrent.futures import ThreadPoolExecutor
-
-import grpc
-import json
-import bittensor
-from . import receptor_impl
-from . import receptor_pool_impl
-
-
-class receptor:
- """ Create and init the receptor object, which encapsulates a grpc connection to an axon endpoint
- """
- def __new__(
- cls,
- endpoint: 'bittensor.Endpoint',
- max_processes: 'int' = 1,
- wallet: 'bittensor.Wallet' = None,
- external_ip: 'str' = None,
- compression: str = None,
- ) -> 'bittensor.Receptor':
- r""" Initializes a receptor grpc connection.
- Args:
- endpoint (:obj:`bittensor.Endpoint`, `required`):
- neuron endpoint descriptor.
- """
-
- if wallet == None:
- wallet = bittensor.wallet()
-
- # Get endpoint string.
- if endpoint.ip == external_ip:
- ip = "localhost:"
- endpoint_str = ip + str(endpoint.port)
- else:
- endpoint_str = endpoint.ip + ':' + str(endpoint.port)
-
- # Determine the grpc compression algorithm
- if compression == 'gzip':
- compress_alg = grpc.Compression.Gzip
- elif compression == 'deflate':
- compress_alg = grpc.Compression.Deflate
- else:
- compress_alg = grpc.Compression.NoCompression
-
- channel = grpc.aio.insecure_channel(
- endpoint_str,
- options=[('grpc.max_send_message_length', -1),
- ('grpc.max_receive_message_length', -1),
- ('grpc.keepalive_time_ms', 100000)])
- stub = bittensor.grpc.BittensorStub( channel )
- return receptor_impl.Receptor(
- endpoint = endpoint,
- channel = channel,
- wallet = wallet,
- stub = stub,
- max_processes=max_processes
- )
-
-
-
-class receptor_pool:
- """ Create and init the receptor_pool object, which manage a pool of grpc connections
- """
- def __new__(
- cls,
- wallet: 'bittensor.Wallet',
- max_active_receptors: int = 4096,
- compression: str = None,
- ) -> 'bittensor.ReceptorPool':
- r""" Initializes a receptor grpc connection.
- Args:
- wallet (:obj:`bittensor.Wallet`, `required`):
- bittensor wallet with hotkey and coldkeypub.
- max_active_receptors (:type:`int`, `optional`):
- Maximum allowed active allocated TCP connections.
- """
- return receptor_pool_impl.ReceptorPool (
- wallet = wallet,
- max_active_receptors = max_active_receptors,
- compression = compression
- )
\ No newline at end of file
diff --git a/commune/modules/bittensor/receptor/receptor_impl.py b/commune/modules/bittensor/receptor/receptor_impl.py
deleted file mode 100644
index c70d194af..000000000
--- a/commune/modules/bittensor/receptor/receptor_impl.py
+++ /dev/null
@@ -1,750 +0,0 @@
-""" Encapsulates a grpc connection to an axon endpoint as a standard auto-grad torch.nn.Module.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-import traceback
-
-import bittensor
-from bittensor._synapse import synapse
-import bittensor.utils.stats as stat_utils
-
-import torch
-import asyncio
-import threading
-import uuid
-import sys
-import torch.nn as nn
-import grpc
-import time as clock
-
-from types import SimpleNamespace
-from typing import Tuple, List, Union
-from loguru import logger
-from grpc import _common
-
-
-
-class Receptor(nn.Module):
-
- def __init__(
- self,
- wallet: 'bittensor.wallet',
- endpoint: 'bittensor.Endpoint',
- channel: 'grpc._Channel',
- stub: 'bittensor.grpc.BittensorStub',
- max_processes: int,
- ):
- r""" Initializes a receptor grpc connection.
-
- Args:
- wallet (:obj:`bittensor.Wallet`, `required`):
- bittensor wallet with hotkey and coldkeypub.
- endpoint (:obj:`bittensor.Endpoint`, `required`):
- neuron endpoint descriptor proto.
- channel (:obj:`grpc._Channel`, `required`):
- grpc TCP channel.
- endpoint (:obj:`bittensor.grpc.BittensorStub`, `required`):
- bittensor protocol stub created from channel.
- """
- super().__init__()
- self.wallet = wallet # Keypair information
- self.endpoint = endpoint # Endpoint information.
- self.channel = channel
- self.stub = stub
- self.receptor_uid = str(uuid.uuid1())
- self.semaphore = threading.Semaphore(max_processes)
- self.state_dict = _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY
- self.stats = SimpleNamespace(
- forward_qps = stat_utils.timed_rolling_avg(0.0, 0.01),
- backward_qps = stat_utils.timed_rolling_avg(0.0, 0.01),
- forward_elapsed_time = stat_utils.timed_rolling_avg(0.0, 0.01),
- forward_bytes_out = stat_utils.timed_rolling_avg(0.0, 0.01),
- forward_bytes_in = stat_utils.timed_rolling_avg(0.0, 0.01),
- backward_bytes_out = stat_utils.timed_rolling_avg(0.0, 0.01),
- backward_bytes_in = stat_utils.timed_rolling_avg(0.0, 0.01),
- codes = {
- bittensor.proto.ReturnCode.NoReturn: 0,
- bittensor.proto.ReturnCode.Success: 0,
- bittensor.proto.ReturnCode.Timeout: 0,
- bittensor.proto.ReturnCode.Backoff: 0,
- bittensor.proto.ReturnCode.Unavailable: 0,
- bittensor.proto.ReturnCode.NotImplemented: 0,
- bittensor.proto.ReturnCode.EmptyRequest: 0,
- bittensor.proto.ReturnCode.EmptyResponse: 0,
- bittensor.proto.ReturnCode.InvalidResponse: 0,
- bittensor.proto.ReturnCode.InvalidRequest: 0,
- bittensor.proto.ReturnCode.RequestShapeException: 0,
- bittensor.proto.ReturnCode.ResponseShapeException: 0,
- bittensor.proto.ReturnCode.RequestSerializationException: 0,
- bittensor.proto.ReturnCode.ResponseSerializationException: 0,
- bittensor.proto.ReturnCode.RequestDeserializationException: 0,
- bittensor.proto.ReturnCode.ResponseDeserializationException: 0,
- bittensor.proto.ReturnCode.NotServingNucleus: 0,
- bittensor.proto.ReturnCode.NucleusTimeout: 0,
- bittensor.proto.ReturnCode.NucleusFull: 0,
- bittensor.proto.ReturnCode.RequestIncompatibleVersion: 0,
- bittensor.proto.ReturnCode.ResponseIncompatibleVersion: 0,
- bittensor.proto.ReturnCode.SenderUnknown: 0,
- bittensor.proto.ReturnCode.UnknownException: 0,
- bittensor.proto.ReturnCode.Unauthenticated: 0,
- bittensor.proto.ReturnCode.BadEndpoint: 0,
- }
- )
-
- def __str__ ( self ):
- return "Receptor({})".format(self.endpoint)
-
- def __repr__ ( self ):
- return self.__str__()
-
- def __del__ ( self ):
- try:
- result = self.channel._channel.check_connectivity_state(True)
- if self.state_dict[result] != self.state_dict[result].SHUTDOWN:
- loop = asyncio.get_event_loop()
- loop.run_until_complete ( self.channel.close() )
- except:
- pass
-
- def __exit__ ( self ):
- self.__del__()
-
- def sign_v1( self ):
- r""" Uses the wallet pubkey to sign a message containing the pubkey and the time
- """
- nonce = self.nonce()
- message = str(nonce) + str(self.wallet.hotkey.ss58_address) + str(self.receptor_uid)
- spliter = 'bitxx'
- signature = spliter.join([ str(nonce), str(self.wallet.hotkey.ss58_address), "0x" + self.wallet.hotkey.sign(message).hex(), str(self.receptor_uid) ])
- return signature
-
- def sign_v2(self):
- nonce = f"{self.nonce()}"
- sender_hotkey = self.wallet.hotkey.ss58_address
- receiver_hotkey = self.endpoint.hotkey
- message = f"{nonce}.{sender_hotkey}.{receiver_hotkey}.{self.receptor_uid}"
- signature = f"0x{self.wallet.hotkey.sign(message).hex()}"
- return ".".join([nonce, sender_hotkey, signature, self.receptor_uid])
-
- def sign(self):
- if self.endpoint.version >= bittensor.__new_signature_version__:
- return self.sign_v2()
- return self.sign_v1()
-
- def nonce ( self ):
- r"""creates a string representation of the time
- """
- return clock.monotonic_ns()
-
- def state ( self ):
- try:
- return self.state_dict[self.channel._channel.check_connectivity_state(True)]
- except ValueError:
- return "Channel closed"
-
- def close ( self ):
- self.__exit__()
-
- def forward (
- self,
- synapses: List[ 'bittensor.Synapse' ],
- inputs: torch.Tensor,
- timeout: int,
- ) -> Tuple[ List[ torch.FloatTensor ], List['bittensor.proto.ReturnCode'], List[float] ]:
- r""" Triggers the grpc call to the remote endpoint.
- This triggers the synapse calls with arguments.
- Call returns a list of output tensors one per synapse with corresponding time and bittensor.proto.ReturnCode.
-
- Args:
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`torch.Tensor` of shape :obj:`(shape)`, `required`):
- Single torch tensor to be sent to the remote endpoint.
- TODO(const): Make this a multi-forward tensor.
-
- timeout (:obj:`int`, `required`):
- Request max timeout
- Returns:
- outputs (:obj:`List[ Union[torch.FloatTensor, torch.LongTensor] ]`, `required`):
- outputs.shape = [batch_size, synapse_length, response]
- List of result tensors from the forward call each corresponding to a passed synapse enum.
-
- codes (:obj:`bittensor.proto.ReturnCode`, `required`):
- List of return codes associated with each passed synapse enum.
- Connection failures return all the same code, otherwise a unique code per synapse.
-
- times (:obj:`float`, `required`):
- List of times for each call associated with each passed synapse enum.
- Success responses all get the same time.
-
- """
- loop = asyncio.get_event_loop()
- return loop.run_until_complete( self.async_forward ( synapses = synapses,inputs = inputs, timeout = timeout ) )
-
-
- def backward (
- self,
- synapses: List[ 'bittensor.Synapse' ],
- inputs: torch.Tensor,
- grads: List[torch.Tensor],
- timeout: int
- ) -> Tuple[ List[ torch.FloatTensor ], List['bittensor.proto.ReturnCode'], List[float] ]:
- r""" Triggers the grpc backward call to the remote endpoint.
- This triggers the synapse's backward calls with arguments.
- Call returns a list of output gradient tensors one per synapse with corresponding time and bittensor.proto.ReturnCode.
-
- Args:
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`torch.Tensor` of shape :obj:`(shape)`, `required`):
- Single torch tensor input corresponding to the linked forward call.
- TODO(const): Make this multi-forward tensor.
-
- grads (:obj:`List[torch.FloatTensor]` of shape :obj:`num_synapses * (shape_of_synapse_output_i)`, `required`):
- List of torch tensor gradients associated with each synapse.
-
- timeout (:obj:`int`, `required`):
- Request max timeout
- Returns:
- output (:obj:`torch.FloatTensor`, `required`):
- Result tensors (likely zero) from the backward call each corresponding to a single forward input.
- NOTE(const) Always zeros because responses are not waited.
- TODO(const): Make this multi-forward tensor.
-
- codes (:obj:`bittensor.proto.ReturnCode`, `required`):
- List of return codes associated with each passed synapse enum.
- Connection failures return all the same code, otherwise a unique code per synapse.
-
- times (:obj:`float`, `required`):
- List of times for each call associated with each passed synapse enum.
- Success responses all get the same time.
- """
- loop = asyncio.get_event_loop()
- return loop.run_until_complete ( self.async_backward ( synapses = synapses, inputs = inputs, grads = grads, timeout = timeout ) )
-
- async def async_forward (
- self,
- synapses: List[ 'bittensor.Synapse' ],
- inputs: torch.Tensor,
- timeout: int,
- ) -> Tuple[ List[ torch.FloatTensor ], List['bittensor.proto.ReturnCode'], List[float] ]:
- r""" Triggers the grpc call to the remote endpoint.
- This triggers the synapse calls with arguments.
- Call returns a list of output tensors one per synapse with corresponding time and bittensor.proto.ReturnCode.
-
- Args:
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`torch.Tensor` of shape :obj:`(shape)`, `required`):
- Single torch tensor to be sent to the remote endpoint.
- TODO(const): Make this a multi-forward tensor.
-
- timeout (:obj:`int`, `required`):
- Request max timeout
- Returns:
- outputs (:obj:`List[ Union[torch.FloatTensor, torch.LongTensor] ]`, `required`):
- outputs.shape = [batch_size, synapse_length, response]
- List of result tensors from the forward call each corresponding to a passed synapse enum.
-
- codes (:obj:`bittensor.proto.ReturnCode`, `required`):
- List of return codes associated with each passed synapse enum.
- Connection failures return all the same code, otherwise a unique code per synapse.
-
- times (:obj:`float`, `required`):
- List of times for each call associated with each passed synapse enum.
- Success responses all get the same time.
-
- """
- # =====================
- # ==== Init params ====
- # =====================
- # These items are filled through the call and the function returns
- # when all codes are non-success or the function finishes completely.
- synapse_messages = [ "Success" for _ in synapses ]
- synapse_codes = [ bittensor.proto.ReturnCode.Success for _ in synapses ]
- synapse_responses = [ synapse.nill_forward_response_tensor( inputs ) for synapse in synapses ]
- synapse_is_response = [ False for _ in synapses ]
- synapse_call_times = [ 0 for _ in synapses ]
- start_time = clock.time()
-
- # ==================================================================
- # ==== Function which returns true if all codes are non success ====
- # ==================================================================
- def check_if_should_return() -> bool:
- for code in synapse_codes:
- if code == bittensor.proto.ReturnCode.Success:
- return False
- return True
-
- # ==============================================================
- # ==== Function which prints all log statements per synapse ====
- # ==============================================================
- def finalize_stats_and_logs():
- self.stats.forward_elapsed_time.update( clock.time() - start_time )
- for index, synapse in enumerate( synapses ):
- self.stats.codes[ synapse_codes[ index ] ] += 1
- bittensor.logging.rpc_log (
- axon = False,
- forward = True,
- is_response = synapse_is_response [index],
- code = synapse_codes[ index ],
- call_time = synapse_call_times[ index ],
- pubkey = self.endpoint.hotkey,
- uid = self.endpoint.uid,
- inputs = list(inputs.shape),
- outputs = None if synapse_codes[ index ] != bittensor.proto.ReturnCode.Success else list( synapse_responses[index].shape ),
- message = synapse_messages[ index ],
- synapse = synapse.synapse_type
- )
-
- # ===========================
- # ==== Check inputs size ====
- # ===========================
- if torch.numel(inputs) == 0:
- # Inputs are nill.
- code = bittensor.proto.ReturnCode.EmptyRequest
- call_time = clock.time() - start_time
- message = "Empty Request"
- synapse_codes = [ code for _ in synapses ]
- synapse_call_times = [ call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ========================
- # ==== Check endpoint ====
- # ========================
- if self.endpoint.hotkey == 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX':
- # Endpoint is dummy.
- code = bittensor.proto.ReturnCode.BadEndpoint
- call_time = clock.time() - start_time
- message = "Bad endpoint."
- synapse_call_times = [ call_time for _ in synapses ]
- synapse_codes = [ code for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ==========================
- # ==== Serialize inputs ====
- # ==========================
- serialized_forward_tensors = []
- serialized_synapses = []
- for index, synapse in enumerate( synapses ):
- try:
- serialized_forward_tensors.append( synapse.serialize_forward_request_tensor ( inputs ))
- serialized_synapses.append(synapse.serialize_to_wire_proto())
- except Exception as e:
- synapse_codes [index] = bittensor.proto.ReturnCode.RequestSerializationException
- synapse_call_times [index] = clock.time() - start_time
- synapse_messages [index] = 'Input serialization exception with error:{}'.format(str(e))
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ============================
- # ==== Build proto request ====
- # ============================
- try:
- grpc_request = bittensor.proto.TensorMessage (
- version = bittensor.__version_as_int__,
- hotkey = self.wallet.hotkey.ss58_address,
- tensors = serialized_forward_tensors,
- synapses = serialized_synapses,
- requires_grad = True,
- )
- except Exception as e:
- # Synapse request creation failed.
- code = bittensor.proto.ReturnCode.UnknownException
- call_time = clock.time() - start_time
- message = 'Request proto creation failed with error:{}'.format(str(e))
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
-
- # ===============================
- # ==== Fire Asyncio RPC Call ====
- # ===============================
- try:
- self.stats.forward_qps.update(1)
- self.stats.forward_bytes_out.update( sys.getsizeof( grpc_request ) )
- finalize_stats_and_logs()
- asyncio_future = self.stub.Forward (
- request = grpc_request,
- timeout = timeout,
- metadata = (
- ('rpc-auth-header','Bittensor'),
- ('bittensor-signature',self.sign()),
- ('bittensor-version',str(bittensor.__version_as_int__)),
- ('request_type', str(bittensor.proto.RequestType.FORWARD)),
- ))
- grpc_response = await asyncio.wait_for(asyncio_future, timeout=timeout)
- self.stats.forward_bytes_in.update( grpc_response.ByteSize() )
- synapse_is_response = [ True for _ in synapses ]
-
- # ====================================
- # ==== Handle GRPC Errors ====
- # ====================================
- except grpc.RpcError as rpc_error_call:
- # Request failed with GRPC code.
- call_time = clock.time() - start_time
- grpc_code = rpc_error_call.code()
- if grpc_code == grpc.StatusCode.DEADLINE_EXCEEDED:
- code = bittensor.proto.ReturnCode.Timeout
- message = 'grpc.StatusCode.DEADLINE_EXCEEDED'+': '+ rpc_error_call.details()
- elif grpc_code == grpc.StatusCode.UNAVAILABLE:
- code = bittensor.proto.ReturnCode.Unavailable
- message = 'grpc.StatusCode.UNAVAILABLE'+': '+ rpc_error_call.details()
- elif grpc_code == grpc.StatusCode.UNAUTHENTICATED:
- code = bittensor.proto.ReturnCode.Unauthenticated
- message = 'grpc.StatusCode.UNAUTHENTICATED'+': '+ rpc_error_call.details()
- else:
- code = bittensor.proto.ReturnCode.UnknownException
- message = 'GRPC error code: {}, details: {}'.format( grpc_code, str(rpc_error_call.details()) )
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- except asyncio.TimeoutError:
- code = bittensor.proto.ReturnCode.Timeout
- call_time = clock.time() - start_time
- message = 'GRPC request timeout after: {}s'.format(timeout)
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ====================================
- # ==== Handle GRPC Unknown Errors ====
- # ====================================
- except Exception as e:
- # Request failed with unknown exception.
- code = bittensor.proto.ReturnCode.UnknownException
- call_time = clock.time() - start_time
- message = 'GRPC request failed with unknown exception:{}'.format(str(e))
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
-
- # ==========================================
- # ==== Handle Non Success GRPC Response ====
- # ==========================================
- if grpc_response.return_code != bittensor.proto.ReturnCode.Success:
- # Request failed with unknown exception.
- call_time = clock.time() - start_time
- synapse_call_times = [call_time for _ in synapses ]
- if len(grpc_response.synapses) == len(synapses):
- synapse_codes = [synapse.return_code for synapse in grpc_response.synapses ]
- synapse_messages = ['Remote Server Failure: '+ synapse.message for synapse in grpc_response.synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
-
-
- # ======================================
- # ==== Check response length ====
- # ======================================
- if ( len(grpc_response.tensors) != len(grpc_response.synapses) ) or ( len(grpc_response.tensors) != len(synapses) ):
- # Not enough responses per request.
- code = bittensor.proto.ReturnCode.ResponseShapeException
- call_time = clock.time() - start_time
- message = "Responses dont match synape length"
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ======================================
- # ==== Check for non success response codes ====
- # ======================================
- for index, wire_synapse in enumerate( grpc_response.synapses ):
- if wire_synapse.return_code != bittensor.proto.ReturnCode.Success:
- synapse_codes[index] = wire_synapse.return_code
- synapse_messages[index] = wire_synapse.message
- synapse_call_times[index] = clock.time() - start_time
-
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ======================================
- # ==== Deserialize synapse responses ====
- # ======================================
- for index, response_proto in enumerate(grpc_response.tensors):
- try:
- synapse = synapses[index]
- if synapse_codes[index] == bittensor.proto.ReturnCode.Success:
- synapse_responses[index] = synapse.deserialize_forward_response_proto ( inputs, response_proto )
- except Exception as e:
- # Input Serialization failed.
- synapse_codes[index] = bittensor.proto.ReturnCode.ResponseDeserializationException
- synapse_call_times[index] = clock.time() - start_time
- synapse_messages[index] = 'Response deserialization exception with error:{}'.format(str(e))
-
-
- # ======================================
- # ==== Finalize forward call times ====
- # ======================================
- for index, _ in enumerate( synapses ):
- if synapse_codes[index] == bittensor.proto.ReturnCode.Success:
- synapse_call_times[index] = clock.time() - start_time
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- async def async_backward (
- self,
- synapses: List[ 'bittensor.Synapse' ],
- inputs: torch.Tensor,
- grads: List[torch.Tensor],
- timeout: int
- ) -> Tuple[ List[ torch.FloatTensor ], List['bittensor.proto.ReturnCode'], List[float] ]:
- r""" Triggers the grpc backward call to the remote endpoint.
- This triggers the synapse's backward calls with arguments.
- Call returns a list of output gradient tensors one per synapse with corresponding time and bittensor.proto.ReturnCode.
-
- Args:
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`torch.Tensor` of shape :obj:`(shape)`, `required`):
- Single torch tensor input corresponding to the linked forward call.
- TODO(const): Make this multi-forward tensor.
-
- grads (:obj:`List[torch.FloatTensor]` of shape :obj:`num_synapses * (shape_of_synapse_output_i)`, `required`):
- List of torch tensor gradients associated with each synapse.
-
- timeout (:obj:`int`, `required`):
- Request max timeout
- Returns:
- output (:obj:`torch.FloatTensor`, `required`):
- Result tensors (likely zero) from the backward call each corresponding to a single forward input.
- NOTE(const) Always zeros because responses are not waited.
- TODO(const): Make this multi-forward tensor.
-
- codes (:obj:`bittensor.proto.ReturnCode`, `required`):
- List of return codes associated with each passed synapse enum.
- Connection failures return all the same code, otherwise a unique code per synapse.
-
- times (:obj:`float`, `required`):
- List of times for each call associated with each passed synapse enum.
- Success responses all get the same time.
- """
- # =====================
- # ==== Init params ====
- # =====================
- # These items are filled through the call and the function returns
- # when all codes are non-success or the function finishes completely.
- synapse_messages = [ "Success" for _ in synapses ]
- synapse_codes = [ bittensor.proto.ReturnCode.Success for _ in synapses ]
- synapse_responses = [ synapse.nill_backward_response_tensor ( inputs ) for synapse in synapses ]
- synapse_is_response = [ False for _ in synapses ]
- synapse_call_times = [ 0 for _ in synapses ]
- start_time = clock.time()
-
- # ==================================================================
- # ==== Function which returns true if all codes are non success ====
- # ==================================================================
- def check_if_should_return() -> bool:
- for code in synapse_codes:
- if code == bittensor.proto.ReturnCode.Success:
- return False
- return True
-
- # ==============================================================
- # ==== Function which prints all log statements per synapse ====
- # ==============================================================
- def finalize_stats_and_logs():
- for index, synapse in enumerate( synapses ):
- self.stats.codes[ synapse_codes[ index ] ] += 1
- bittensor.logging.rpc_log (
- axon = False,
- forward = False,
- is_response = synapse_is_response [index],
- code = synapse_codes[ index ],
- call_time = synapse_call_times[ index ],
- pubkey = self.endpoint.hotkey,
- uid = self.endpoint.uid,
- inputs = list(grads[index].shape),
- outputs = None,
- message = synapse_messages[ index ],
- synapse = synapse.synapse_type
- )
-
- # ========================
- # ==== Check endpoint ====
- # ========================
- if self.endpoint.hotkey == 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX':
- # Endpoint is dummy.
- code = bittensor.proto.ReturnCode.BadEndpoint
- call_time = clock.time() - start_time
- message = "Bad endpoint."
- synapse_call_times = [ call_time for _ in synapses ]
- synapse_codes = [ code for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ==================================
- # ==== Serialize inputs & grads ====
- # ==================================
- serialized_forward_tensors = []
- serialized_backward_grads = []
- serialized_synapses = []
- for index, synapse in enumerate( synapses ):
- try:
- serialized_forward_tensors.append(synapse.serialize_forward_request_tensor( inputs ))
- serialized_backward_grads.append(synapse.serialize_backward_request_gradient (inputs, grads[index] ))
- serialized_synapses.append(synapse.serialize_to_wire_proto())
- except Exception as e:
- # Input Serialization failed.
- synapse_codes [index] = bittensor.proto.ReturnCode.RequestSerializationException
- synapse_call_times [index] = clock.time() - start_time
- synapse_messages [index] = 'Input serialization exception with error:{}'.format(str(e))
- # Check if the call can stop here.
- if check_if_should_return():
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
-
- # =============================
- # ==== Build proto request ====
- # =============================
- try:
- grpc_request = bittensor.proto.TensorMessage (
- version = bittensor.__version_as_int__,
- hotkey = self.wallet.hotkey.ss58_address,
- tensors = serialized_forward_tensors + serialized_backward_grads,
- synapses = serialized_synapses,
- requires_grad = True,
- )
-
- except Exception as e:
- # Synapse request creation failed.
- code = bittensor.proto.ReturnCode.UnknownException
- call_time = clock.time() - start_time
- message = 'Request proto creation failed with error:{}'.format(str(e))
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # =======================
- # ==== Make RPC Call ====
- # =======================
- try:
- self.stats.backward_qps.update(1)
- self.stats.backward_bytes_out.update(sys.getsizeof(grpc_request))
- # Fire and forget.
- asyncio_future = self.stub.Backward(
- request = grpc_request,
- timeout = timeout,
- metadata = (
- ('rpc-auth-header','Bittensor'),
- ('bittensor-signature',self.sign()),
- ('bittensor-version',str(bittensor.__version_as_int__)),
- ('request_type', str(bittensor.proto.RequestType.BACKWARD)),
- ))
- asyncio_future.cancel()
-
- # ====================================
- # ==== Handle GRPC Errors ====
- # ====================================
- except grpc.RpcError as rpc_error_call:
-
- # Request failed with GRPC code.
- call_time = clock.time() - start_time
- grpc_code = rpc_error_call.code()
- if grpc_code == grpc.StatusCode.DEADLINE_EXCEEDED:
- code = bittensor.proto.ReturnCode.Timeout
- message = 'grpc.StatusCode.DEADLINE_EXCEEDED'+': '+ rpc_error_call.details()
- elif grpc_code == grpc.StatusCode.UNAVAILABLE:
- code = bittensor.proto.ReturnCode.Unavailable
- message = 'grpc.StatusCode.UNAVAILABLE'+': '+ rpc_error_call.details()
- elif grpc_code == grpc.StatusCode.UNAUTHENTICATED:
- code = bittensor.proto.ReturnCode.Unauthenticated
- message = 'grpc.StatusCode.UNAUTHENTICATED'+': '+ rpc_error_call.details()
- else:
- code = bittensor.proto.ReturnCode.UnknownException
- message = 'GRPC error code: {}, details: {}'.format( grpc_code, str(rpc_error_call.details()) )
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
-
- # =======================
- # ==== Timeout Error ====
- # =======================
- except asyncio.TimeoutError:
- code = bittensor.proto.ReturnCode.Timeout
- call_time = clock.time() - start_time
- message = 'GRPC request timeout after: {}s'.format(timeout)
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
- # ====================================
- # ==== Handle GRPC Unknown Errors ====
- # ====================================
- except Exception as e:
-
- # Request failed with unknown exception.
- code = bittensor.proto.ReturnCode.UnknownException
- call_time = clock.time() - start_time
- message = 'GRPC request failed with unknown exception:{}'.format(str(e))
- synapse_codes = [code for _ in synapses ]
- synapse_call_times = [call_time for _ in synapses ]
- synapse_messages = [ message for _ in synapses ]
-
- # ======================================
- # ==== Finalize backward call times ====
- # ======================================
- for index, _ in enumerate( synapses ):
- if synapse_codes[index] == bittensor.proto.ReturnCode.Success:
- synapse_call_times[index] = clock.time() - start_time
- finalize_stats_and_logs()
- return synapse_responses, synapse_codes, synapse_call_times
-
-
-
-
-
-
-
diff --git a/commune/modules/bittensor/receptor/receptor_pool_impl.py b/commune/modules/bittensor/receptor/receptor_pool_impl.py
deleted file mode 100644
index 6bdbd85ea..000000000
--- a/commune/modules/bittensor/receptor/receptor_pool_impl.py
+++ /dev/null
@@ -1,423 +0,0 @@
-""" Manages a pool of grpc connections as receptors
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import math
-from typing import Tuple, List, Union
-from threading import Lock
-import streamlit as st
-import torch
-import asyncio
-from loguru import logger
-import concurrent
-import bittensor
-from bittensor._endpoint import endpoint
-import bittensor.utils.networking as net
-from concurrent.futures import ThreadPoolExecutor
-import commune
-
-logger = logger.opt(colors=True)
-
-
-class ReceptorPool ( torch.nn.Module):
- """ Manages a pool of grpc connections as receptors
- """
- def __init__(
- self,
- wallet: 'bittensor.Wallet',
- max_active_receptors: int = 1000,
- compression: str = None,
- ):
- super().__init__()
- self.wallet = wallet
- self.max_active_receptors = max_active_receptors
- self.receptors = {}
- self.cull_mutex = Lock()
- self.max_processes = 10
- self.compression = compression
- self.total_requests = 0
-
- try:
- self.external_ip = str(net.get_external_ip())
- except Exception:
- self.external_ip = None
-
-
-
- def __str__(self):
- return "ReceptorPool({},{})".format(len(self.receptors), self.max_active_receptors)
-
- def __repr__(self):
- return self.__str__()
-
- def __exit__(self):
- for receptor in self.receptors:
- receptor.__del__()
-
- def get_total_requests(self):
- return self.total_requests
- def get_receptors_state(self):
- r""" Return the state of each receptor.
- Returns:
- states (:obj:`List[grpc.channel.state]`)
- The state of receptor.
- """
- return {hotkey: v.state() for hotkey, v in self.receptors.items()}
-
- def forward (
- self,
- endpoints: List [ 'bittensor.Endpoint' ],
- synapses: List[ 'bittensor.Synapse' ],
- inputs: List [ torch.Tensor ],
- timeout: int,
- min_successes: int = None,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Forward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List[ bittensor.Endpoint ]` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of inputs. Tensors from x are sent forward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- TODO(const): Allow multiple tensors.
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- modality.
-
- timeout (int):
- Request timeout.
-
- Returns:
- forward_outputs (:obj:`List[ List[ torch.FloatTensor ]]` of shape :obj:`(num_endpoints * (num_synapses * (shape)))`, `required`):
- Output encodings of tensors produced by remote endpoints. Non-responses are zeroes of common shape.
-
- forward_codes (:obj:`List[ List[bittensor.proto.ReturnCodes] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call return ops.
-
- forward_times (:obj:`List[ List [float] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call times
- """
- if len(endpoints) != len(inputs):
- raise ValueError('Endpoints must have the same length as passed inputs. Got {} and {}'.format(len(endpoints), len(inputs)))
-
- try:
- loop = asyncio.get_event_loop()
- except RuntimeError:
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
- return loop.run_until_complete (
- self.async_forward(
- endpoints = endpoints,
- synapses = synapses,
- inputs = inputs,
- timeout = timeout,
- min_successes = min_successes,
- )
- )
-
-
-
- def backward(
- self,
- endpoints: List [ 'bittensor.Endpoint' ],
- synapses: List[ 'bittensor.Synapse' ],
- inputs: List [ torch.Tensor ],
- grads: List [ List[ torch.FloatTensor ] ],
- timeout: int
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Backward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List['bittensor.Endpoint']` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of x. Tensors from x are sent backward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- synapse.
-
- grads (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- List of list of grad tensors where each grad corresponds to a synapse call on an endpoint.
-
- timeout (int):
- request timeout.
-
- Returns:
- backward_outputs (:obj:`List[ List[ torch.FloatTensor] ]` of shape :obj:`num_endpoints * (batch_size, sequence_len, -1)]`, `required`):
- Gradients returned from the backward call one per endpoint.
-
- backward_codes (:obj:`List[ List[ bittensor.proto.ReturnCodes ] ]` of shape :obj:`(num_endpoints)`, `required`):
- List of list of Backward call return ops, one per endpoint and synapse.
-
- backward_times (:obj:`List[float]` of shape :obj:`(num_endpoints)`, `required`):
- List of list of Backward call times one per endpoint and synapse.
- """
- if len(endpoints) != len(inputs):
- raise ValueError('Endpoints must have the same length as passed inputs. Got {} and {}'.format(len(endpoints), len(inputs)))
- if len(endpoints) != len(grads):
- raise ValueError('Endpoints must have the same length as passed grads_dy. Got {} and {}'.format(len(endpoints), len(grads)))
- for grads_per_synapse in grads:
- if len(grads_per_synapse) != len(synapses):
- raise ValueError('Gradients must have the same length as passed synapses. Got {} and {}'.format(len(grads_per_synapse), len(synapses)))
- try:
- loop = asyncio.get_event_loop()
- except RuntimeError:
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
- return loop.run_until_complete (
- self.async_backward(
- endpoints = endpoints,
- synapses = synapses,
- inputs = inputs,
- grads = grads,
- timeout = timeout
- )
- )
-
- async def async_forward (
- self,
- endpoints: List [ 'bittensor.Endpoint' ],
- synapses: List[ 'bittensor.Synapse' ],
- inputs: List [ torch.Tensor ],
- timeout: int,
- min_successes: int = 20,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Forward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List[ bittensor.Endpoint ]` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of inputs. Tensors from x are sent forward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- TODO(const): Allow multiple tensors.
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- modality.
-
- timeout (int):
- Request timeout.
-
- Returns:
- forward_outputs (:obj:`List[ List[ torch.FloatTensor ]]` of shape :obj:`(num_endpoints * (num_synapses * (shape)))`, `required`):
- Output encodings of tensors produced by remote endpoints. Non-responses are zeroes of common shape.
-
- forward_codes (:obj:`List[ List[bittensor.proto.ReturnCodes] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call return ops.
-
- forward_times (:obj:`List[ List [float] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call times
- """
- # Init receptors.
- receptors = [ self._get_or_create_receptor_for_endpoint( endpoint ) for endpoint in endpoints ]
-
-
-
- loop = asyncio.get_event_loop()
- # Make calls.
- running_tasks = []
- st.write(inputs[0].shape, inputs[0].dtype)
- for index, receptor in enumerate(receptors):
- task = asyncio.create_task(
- receptor.async_forward(
- synapses = synapses,
- inputs = inputs[index],
- timeout = timeout
- )
- )
- running_tasks.append(task)
-
-
- forward_outputs = []
- forward_codes = []
- forward_times = []
- while len(running_tasks) > 0:
-
- finished_tasks, running_tasks = await asyncio.wait( running_tasks , return_when=asyncio.FIRST_COMPLETED)
- finished_tasks, running_tasks = list(finished_tasks), list(running_tasks)
-
- # st.write(len(finished_tasks), len(running_tasks))
- # Unpack responses
-
-
- responses = await asyncio.gather(*finished_tasks)
-
- for response in responses:
- st.write(response[1])
- if min_successes > 0:
- if response[1][0] == 1:
- forward_outputs.append( response[0] )
- forward_codes.append( response[1] )
- forward_times.append( response[2] )
-
- if len(forward_outputs) >= min_successes :
- # cancel the rest of the tasks
- [t.cancel() for t in running_tasks]
- running_tasks = [t for t in running_tasks if t.cancelled()]
- assert len(running_tasks) == 0, f'{len(running_tasks)}'
- break
- else:
-
- forward_outputs.append( response[0] )
- forward_codes.append( response[1] )
- forward_times.append( response[2] )
-
-
- # ---- Kill receptors ----
- # self._destroy_receptors_over_max_allowed()
- # ---- Return ----
- return forward_outputs, forward_codes, forward_times
-
- async def async_backward(
- self,
- endpoints: List [ 'bittensor.Endpoint' ],
- synapses: List[ 'bittensor.Synapse' ],
- inputs: List [ torch.Tensor ],
- grads: List [ List[ torch.FloatTensor ] ],
- timeout: int
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Backward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List['bittensor.Endpoint']` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of x. Tensors from x are sent backward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- synapse.
-
- grads (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- List of list of grad tensors where each grad corresponds to a synapse call on an endpoint.
-
- timeout (int):
- request timeout.
-
- Returns:
- backward_outputs (:obj:`List[ List[ torch.FloatTensor] ]` of shape :obj:`num_endpoints * (batch_size, sequence_len, -1)]`, `required`):
- Gradients returned from the backward call one per endpoint.
-
- backward_codes (:obj:`List[ List[ bittensor.proto.ReturnCodes ] ]` of shape :obj:`(num_endpoints)`, `required`):
- List of list of Backward call return ops, one per endpoint and synapse.
-
- backward_times (:obj:`List[float]` of shape :obj:`(num_endpoints)`, `required`):
- List of list of Backward call times one per endpoint and synapse.
- """
- # Init receptors.
- receptors = [ self._get_or_create_receptor_for_endpoint( endpoint ) for endpoint in endpoints ]
-
- # Make calls.
- calls = []
- for index, receptor in enumerate(receptors):
- calls.append(
- receptor.async_backward (
- synapses = synapses,
- inputs = inputs[index],
- grads = grads[index],
- timeout = timeout
- )
- )
- responses = await asyncio.gather( *calls )
-
- # Unpack responses
- backward_outputs = []
- backward_codes = []
- backward_times = []
- for response in responses:
- backward_outputs.append( response[0] )
- backward_codes.append( response[1] )
- backward_times.append( response[2] )
-
- # ---- Kill receptors ----
- self._destroy_receptors_over_max_allowed()
- # ---- Return ----
- return backward_outputs, backward_codes, backward_times
-
- def _destroy_receptors_over_max_allowed( self ):
- r""" Destroys receptors based on QPS until there are no more than max_active_receptors.
- """
- with self.cull_mutex:
- # ---- Finally: Kill receptors over max allowed ----
- while len(self.receptors) > self.max_active_receptors:
- min_receptor_qps = math.inf
- receptor_to_remove = None
- for next_receptor in self.receptors.values():
- next_qps = next_receptor.stats.forward_qps.value
- sema_value = next_receptor.semaphore._value
- if (min_receptor_qps > next_qps) and (sema_value == self.max_processes):
- receptor_to_remove = next_receptor
- min_receptor_qps = next_receptor.stats.forward_qps.value
-
- if receptor_to_remove != None:
- try:
- bittensor.logging.destroy_receptor_log(receptor_to_remove.endpoint)
- self.receptors[ receptor_to_remove.endpoint.hotkey ].close()
- del self.receptors[ receptor_to_remove.endpoint.hotkey ]
- except KeyError:
- pass
- elif receptor_to_remove == None:
- break
-
- def _get_or_create_receptor_for_endpoint( self, endpoint: 'bittensor.Endpoint' ) -> 'bittensor.Receptor':
- r""" Finds or creates a receptor TCP connection associated with the passed Neuron Endpoint
- Returns
- receptor: (`bittensor.Receptor`):
- receptor with tcp connection endpoint at endpoint.ip:endpoint.port
- """
- # ---- Find the active receptor for this endpoint ----
- if endpoint.hotkey in self.receptors :
- receptor = self.receptors[ endpoint.hotkey ]
-
- # Change receptor address.
- if receptor.endpoint.ip != endpoint.ip or receptor.endpoint.port != endpoint.port:
- #receptor.close()
- bittensor.logging.update_receptor_log( endpoint )
- receptor = bittensor.receptor (
- endpoint = endpoint,
- wallet = self.wallet,
- external_ip = self.external_ip,
- max_processes = self.max_processes
- )
- self.receptors[ receptor.endpoint.hotkey ] = receptor
-
- # ---- Or: Create a new receptor ----
- else:
- bittensor.logging.create_receptor_log( endpoint )
- receptor = bittensor.receptor (
- endpoint = endpoint,
- wallet = self.wallet,
- external_ip = self.external_ip,
- max_processes = self.max_processes,
- compression = self.compression
- )
- self.receptors[ receptor.endpoint.hotkey ] = receptor
-
- return receptor
- def getattr(self, *args, **kwargs):
- return self.__getattribute__( *args, **kwargs)
diff --git a/commune/modules/bittensor/relayer/dendrite/__init__.py b/commune/modules/bittensor/relayer/dendrite/__init__.py
deleted file mode 100644
index 87a4ebe67..000000000
--- a/commune/modules/bittensor/relayer/dendrite/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .model import DendriteModel
\ No newline at end of file
diff --git a/commune/modules/bittensor/relayer/dendrite_model.py b/commune/modules/bittensor/relayer/dendrite_model.py
deleted file mode 100644
index 37e5d88de..000000000
--- a/commune/modules/bittensor/relayer/dendrite_model.py
+++ /dev/null
@@ -1,345 +0,0 @@
-import torch
-import os,sys
-import asyncio
-from transformers import AutoConfig, PreTrainedTokenizerBase
-# import streamlit as st
-
-
-from typing import List, Union, Dict
-from munch import Munch
-
-import commune
-commune.new_event_loop()
-
-from commune.block.bittensor.receptor import receptor_pool
-import bittensor
-from bittensor.utils.tokenizer_utils import phrase_cross_entropy, topk_token_phrases, prep_tokenizer
-
-from copy import deepcopy
-class DendriteModel(torch.nn.Module, commune.Module):
-
- def __init__(self,
- uids : List[int] = [441],
- wallet:bittensor.wallet = None,
- tokenizer: bittensor.tokenizer = None,
- subtensor: bittensor.subtensor = None,
- metagraph: bittensor.metagraph = None,
- model_name:str = 'model.dendrite',
- metric:str = 'incentive',
- hidden_size = 8
- ):
-
- torch.nn.Module.__init__(self)
-
- self.metric = metric
-
- self.loss = torch.nn.CrossEntropyLoss()
- self.loop = self.set_event_loop(new_loop=True)
-
-
- self.set_event_loop(new_loop=True)
-
- self.model_name = model_name
- self.model_config = Munch(AutoConfig.from_pretrained('gpt2').__dict__)
- self.model_config.hidden_size = hidden_size
-
- self.wallet = wallet if wallet else self.default_wallet()
- self.tokenizer = tokenizer if tokenizer else bittensor.tokenizer()
- self.tokenizer = prep_tokenizer(self.tokenizer, self.tokenizer)
- self.subtensor = subtensor if subtensor else self.default_subtensor()
-
- self.relay_neurons = [self.subtensor.neuron_for_uid(uid) for uid in uids]
-
- self.endpoints = [bittensor.endpoint.from_neuron(neuron) for neuron in self.relay_neurons]
- self.metagraph = metagraph if metagraph else bittensor.metagraph(subtensor=self.subtensor)
- # self.wallet = self.wallet.register(cuda=True ,subtensor=self.subtensor)
- self.metagraph= self.metagraph.load()
- self.metagraph.sync()
-
- self.receptor_pool = receptor_pool(wallet=self.wallet)
-
-
- def set_endpoints(self, endpoints: Union[str,bittensor.Endpoint]) -> List[str]:
- self.endpoints = []
- for e in endpoints:
- if isinstance(e, bittensor.Wallet):
- e = bittensor.endpoint.from_neuron(e.get_neuron())
- self.endpoints.append(e)
- elif isinstance(e,bittensor.Endpoint):
- self.endpoints.append(e)
- else:
- raise NotImplemented
-
- return self.endpoints
-
- def top_endpoints(self, n:int=30, metric=None):
- metric = metric if metric else self.metric
- top_uid_indices = torch.argsort(getattr(self.metagraph, metric), descending=True)[:n]
- endpoints = self.metagraph.endpoint_objs
- return [endpoints[i] for i in top_uid_indices]
-
- def forward(self,
- input_ids: torch.Tensor,
- attention_mask: torch.Tensor = None,
- output_hidden_states:bool = False,
- output_logits:bool = True,
- num_endpoints:int = 20 ,
- topk: int = 4096,
- timeout: int = 3,
- max_trials: int = 1,
- max_responses: int = 10,
- min_successes = 5,
- **kwargs
- ):
-
-
- endpoints = deepcopy(self.endpoints)
- if num_endpoints > 0:
- endpoints += self.top_endpoints(n=num_endpoints)
- atleast_one_success = False
-
- trial_count = 0
- t = commune.timer()
-
- commune.print(endpoints)
-
- while not atleast_one_success and trial_count < max_trials:
- response = self.receptor_pool.forward(inputs=[input_ids]*len(endpoints) ,
- endpoints=endpoints,
- synapses=[bittensor.synapse.TextCausalLMNext()],
- timeout=timeout,
- min_successes=min_successes)
-
- atleast_one_success = any([any([c==1 for c in codes]) for codes in response[1]])
- trial_count += 1
- commune.print(f'Endpoints: {self.endpoints}', color='purple')
-
- commune.print(f'Responses from Server Codes: {response[1]}', color='yellow')
-
-
-
-
- response_tensors = []
- success_count = 1
- code_count_dict = {}
- max_responses = max_responses if max_responses else num_endpoints
- for i in range(len(response[1])):
- # st.write(response[1][i][0])
-
- # assume the codes are all the same for the endpoint (not a super safe assumption but good for now)
- code = response[1][i][0]
-
-
-
- if code in code_count_dict:
- code_count_dict[code] += 1
- else:
- code_count_dict[code] = 1
-
- if code == 1:
- response_tensors += [response[0][i][0]]
- # if len(response_tensors)>=max_responses:
- # break
-
-
-
-
- metrics = {}
- metrics['num_successes'] = len(response_tensors)
- metrics['num_endpoints'] = len(endpoints)
- metrics['success_rate'] = metrics['num_successes'] / (metrics['num_endpoints'] + 1e-8)
- metrics['seconds'] = t.seconds
- assert metrics['num_successes'] > 0 , f'{code_count_dict}'
-
-
-
- print('CODE COUNTER: ', code_count_dict)
- output_dict = {}
- logits = self.mix_response(response_tensors)
-
- if output_logits:
- logits = self.mix_response(response_tensors)
- output_dict['logits'] = logits
-
- commune.print(len(response_tensors), 'green')
- if topk:
- if len(response_tensors) > 1:
- output_dict['topk'] = self.encode_topk(logits[..., -1:, :])
- else:
- output_dict['topk'] = response_tensors[0].unsqueeze(1)
-
-
- # if output_hidden_states:
- # raise NotImplemented(f'output_hidden_states = {output_hidden_states}')
-
- return output_dict
-
- def get_best_endpoints(self):
- return self.endpoints
-
- def get_loss_fct(self, logits: torch.FloatTensor, labels: torch.LongTensor) -> torch.FloatTensor:
- if not hasattr(self, 'loss'):
- self.loss = torch.nn.CrossEntropyLoss()
-
- """
- Calculate loss_fct, CausalLM loss, next-token prediction loss.
- Args:
- logits (:obj:`torch.FloatTensor`, `required`):
- [batch_size, sequence_len, bittensor.__network_dim__]
- labels (:obj:`torch.LongTensor`, `required`):
- [batch_size, sequence_len]
-
- Returns:
- loss (:obj:`torch.FloatTensor`):
- scalar
- """
- shift_logits = logits[..., :-1, :]
- logits_seq_len = logits.shape[1]
-
- shift_labels = labels[..., -logits_seq_len:]
- shift_labels = shift_labels[..., 1:]
- print(f'LOGITS: {shift_logits.shape} LABELS: {shift_labels.shape}')
- loss = self.loss(shift_logits.reshape(-1, shift_logits.size(-1)), shift_labels.reshape(-1))
-
- return loss
-
-
- @classmethod
- def default_subtensor(cls):
- return bittensor.subtensor(chain_endpoint=os.getenv('SUBTENSOR'))
-
-
- @classmethod
- def default_wallet(cls):
- return bittensor.wallet(name='fish', hotkey='100')
-
- @classmethod
- def default_model(cls):
- self = cls(uids = [441])
- return self
-
- @classmethod
- def test_performance(cls, batch_size= 32, sequence_length=256, num_batches=100):
-
- import time
-
- self = cls.default_model()
- dataset = cls.connect('dataset::bittensor')
- for i in range(num_batches):
- sample = dataset.sample()
- input_ids = sample['input_ids'][:, :-1]
- targets = sample['input_ids'][:,-1:]
-
- t = commune.timer()
- output = self(input_ids=input_ids)
- print('OUTPUT SCHEMA')
- print('TIME (s): ', t.seconds)
- # print(self.get_loss_fct(logits=pred['logits'], labels=input_ids))
- print(output['topk'].shape, targets.shape)
- print(phrase_cross_entropy(topk_tensor=output['topk'][:,-1], target_phrases=targets))
-
-
- @classmethod
- def test(cls):
- cls.test_performance()
- cls.test_neuron()
-
-
- @classmethod
- def run_neuron(cls):
- from commune.neuron.miner import neuron
- model = cls.default_model()
- n = neuron(model=model)
- n.run()
-
- @classmethod
- def mix_response(cls, responses:List[torch.Tensor], routing_scores:list= None):
-
- batch_size = responses[0].shape[0]
- num_models = len(responses)
- device = responses[0].device
-
- if routing_scores == None:
- routing_scores = torch.full(fill_value=1/num_models,size=(num_models,batch_size)).to(device)
- # st.write(routing_scores)
-
- stacked_responses = torch.cat([ r[...,:-1, :2] for r in responses], dim=0)
- decoded_tensors = cls.decode_topk(stacked_responses[:, None]) # [batch_size, 1, sequence_len, vocab_size]
- print(decoded_tensors.shape, routing_scores.shape, routing_scores.sum(dim=0))
-
- decoded_tensors = torch.stack(decoded_tensors.chunk(chunks=num_models, dim=0))
-
- # shappe of decoded_tensors: [num_models, batch_size, sequence_len, vocab_size]
-
-
- merged_tensors = (routing_scores[:,:,None,None]*decoded_tensors).sum(dim=0)
-
- # merged_tensors: [batch_size, sequence_len, vocab_size] -> [batch_size, vocab_size]
- return merged_tensors
-
-
-
- @staticmethod
- def decode_topk( forward_response_tensor: torch.Tensor, vocab_size:int=bittensor.__vocab_size__) -> torch.Tensor:
- """ Returns full logits by decoding topk-encoding input. """
- encoded_probs = forward_response_tensor # encoded probabilities: [batch_size, sequence_len, topk + topk]
-
- if len(encoded_probs.shape) == 3:
- encoded_probs = torch.stack(encoded_probs.chunk(chunks=2, dim=-1), dim=-1)
-
- batch_size, sequence_len, topk, _ = encoded_probs.shape
-
- topk_values = encoded_probs[..., 0] # topk probs: [batch_size, sequence_len, topk]
- topk_indices = encoded_probs[..., 1].long() # topk probs indices: [batch_size, sequence_len, topk]
-
- max_index = torch.max(topk_indices).item()
- vocab_size = max(vocab_size, max_index + 1)
- topk_values = topk_values
- topk_indices = topk_indices
-
-
-
- topk_pmass = topk_values.sum(dim=-1) # topk probability mass: [batch_size, sequence_len]
- remainder_pmass = torch.clamp(1 - topk_pmass, 1e-40, 1) # remainder probability mass: [batch_size, sequence_len]
- remainder_floor = remainder_pmass / (vocab_size - topk) # divide remainder: [batch_size, sequence_len]
-
- logits = torch.ones((batch_size, sequence_len, vocab_size), dtype=topk_values.dtype).to(topk_values.device)
- logits *= torch.log(remainder_floor)[:, :, None] # set probability floor: [batch_size, sequence_len, vocab_size]
-
- logits.scatter_(-1, topk_indices, torch.log(topk_values + 1e-40)) # insert topk probs: [batch_size, sequence_len, vocab_size]
-
- return logits # [batch_size, sequence_len, vocab_size]
-
-
-
- @staticmethod
- def encode_topk( forward_response_tensor: torch.Tensor , topk:int=4096, compact:bool = False) -> torch.Tensor:
- """ Returns topk tokens/probabilities given unnormalized logits as input. """
-
- #import ipdb; ipdb.set_trace()
-
- logits = forward_response_tensor # unnormalized logit scores: [batch_size, sequence_len, vocab_size]
- probs = torch.softmax(logits, dim=-1).to(torch.float32) # normalized probabilities: [batch_size, sequence_len, vocab_size]
-
- topk_indices = torch.argsort(probs, dim=-1, descending=True)[...,:topk]
- # topk_values, topk_indices = torch.topk(probs, topk) # topk probs and indices: [batch_size, sequence_len, topk]
-
- topk_values = probs.gather( index=topk_indices, dim=-1)
- if compact:
- encoded_probs = torch.cat([topk_values, topk_indices], dim=-1) # [batch_size, sequence_len, topk + topk]
- else:
- encoded_probs = torch.stack([topk_values, topk_indices], dim=-1) # [batch_size, sequence_len, topk + topk]
-
- return encoded_probs # [batch_size, sequence_len, topk + topk]
-
-
- # def run_pm2()
-
-if __name__ == "__main__":
-
- DendriteModel.run()
-
-
-
-
-
diff --git a/commune/modules/bittensor/subtensor/__init__.py b/commune/modules/bittensor/subtensor/__init__.py
deleted file mode 100644
index f22d018df..000000000
--- a/commune/modules/bittensor/subtensor/__init__.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import copy
-import os
-
-import bittensor
-from loguru import logger
-from substrateinterface import SubstrateInterface
-from torch.cuda import is_available as is_cuda_available
-
-from . import subtensor_impl, subtensor_mock
-
-logger = logger.opt(colors=True)
-
-GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME = 'node-subtensor'
-
-class subtensor:
- """Factory Class for both bittensor.Subtensor and Mock_Subtensor Classes
-
- The Subtensor class handles interactions with the substrate subtensor chain.
- By default, the Subtensor class connects to the Nakamoto which serves as the main bittensor network.
-
- """
-
- def __new__(
- cls,
- config: 'bittensor.config' = None,
- network: str = None,
- chain_endpoint: str = None,
- _mock: bool = None,
- ) -> 'bittensor.Subtensor':
- r""" Initializes a subtensor chain interface.
- Args:
- config (:obj:`bittensor.Config`, `optional`):
- bittensor.subtensor.config()
- network (default='local', type=str)
- The subtensor network flag. The likely choices are:
- -- local (local running network)
- -- finney (main network)
- -- mock (mock network for testing.)
- If this option is set it overloads subtensor.chain_endpoint with
- an entry point node from that network.
- chain_endpoint (default=None, type=str)
- The subtensor endpoint flag. If set, overrides the network argument.
- _mock (bool, `optional`):
- Returned object is mocks the underlying chain connection.
- """
- if config == None: config = subtensor.config()
- config = copy.deepcopy( config )
-
- # Returns a mocked connection with a background chain connection.
- config.subtensor._mock = _mock if _mock != None else config.subtensor._mock
- if config.subtensor._mock == True or network == 'mock' or config.subtensor.get('network', bittensor.defaults.subtensor.network) == 'mock':
- config.subtensor._mock = True
- return subtensor_mock.mock_subtensor.mock()
-
- # Determine config.subtensor.chain_endpoint and config.subtensor.network config.
- # If chain_endpoint is set, we override the network flag, otherwise, the chain_endpoint is assigned by the network.
- # Argument importance: chain_endpoint > network > config.subtensor.chain_endpoint > config.subtensor.network
-
- # Select using chain_endpoint arg.
- if chain_endpoint != None:
- config.subtensor.chain_endpoint = chain_endpoint
- if network != None:
- config.subtensor.network = network
- else:
- config.subtensor.network = config.subtensor.get('network', bittensor.defaults.subtensor.network)
-
- # Select using network arg.
- elif network != None:
- config.subtensor.chain_endpoint = subtensor.determine_chain_endpoint( network )
- config.subtensor.network = network
-
- # Select using config.subtensor.chain_endpoint
- elif config.subtensor.chain_endpoint != None:
- config.subtensor.chain_endpoint = config.subtensor.chain_endpoint
- config.subtensor.network = config.subtensor.get('network', bittensor.defaults.subtensor.network)
-
- # Select using config.subtensor.network
- elif config.subtensor.get('network', bittensor.defaults.subtensor.network) != None:
- config.subtensor.chain_endpoint = subtensor.determine_chain_endpoint( config.subtensor.get('network', bittensor.defaults.subtensor.network) )
- config.subtensor.network = config.subtensor.get('network', bittensor.defaults.subtensor.network)
-
- # Fallback to defaults.
- else:
- config.subtensor.chain_endpoint = subtensor.determine_chain_endpoint( bittensor.defaults.subtensor.network )
- config.subtensor.network = bittensor.defaults.subtensor.network
-
- # make sure it's wss:// or ws://
- # If it's bellagene (parachain testnet) then it has to be wss
- endpoint_url: str = config.subtensor.chain_endpoint
-
- # make sure formatting is good
- endpoint_url = bittensor.utils.networking.get_formatted_ws_endpoint_url(endpoint_url)
-
-
- subtensor.check_config( config )
- network = config.subtensor.get('network', bittensor.defaults.subtensor.network)
-
- substrate = SubstrateInterface(
- ss58_format = bittensor.__ss58_format__,
- use_remote_preset=True,
- url = endpoint_url,
- type_registry=bittensor.__type_registry__
- )
- return subtensor_impl.Subtensor(
- substrate = substrate,
- network = config.subtensor.get('network', bittensor.defaults.subtensor.network),
- chain_endpoint = config.subtensor.chain_endpoint,
- )
-
- @staticmethod
- def config() -> 'bittensor.Config':
- parser = argparse.ArgumentParser()
- subtensor.add_args( parser )
- return bittensor.config( parser )
-
- @classmethod
- def help(cls):
- """ Print help to stdout
- """
- parser = argparse.ArgumentParser()
- cls.add_args( parser )
- print (cls.__new__.__doc__)
- parser.print_help()
-
- @classmethod
- def add_args(cls, parser: argparse.ArgumentParser, prefix: str = None ):
- prefix_str = '' if prefix == None else prefix + '.'
- try:
- parser.add_argument('--' + prefix_str + 'subtensor.network', default = bittensor.defaults.subtensor.network, type=str,
- help='''The subtensor network flag. The likely choices are:
- -- finney (main network)
- -- local (local running network)
- -- mock (creates a mock connection (for testing))
- If this option is set it overloads subtensor.chain_endpoint with
- an entry point node from that network.
- ''')
- parser.add_argument('--' + prefix_str + 'subtensor.chain_endpoint', default = bittensor.defaults.subtensor.chain_endpoint, type=str,
- help='''The subtensor endpoint flag. If set, overrides the --network flag.
- ''')
- parser.add_argument('--' + prefix_str + 'subtensor._mock', action='store_true', help='To turn on subtensor mocking for testing purposes.', default=bittensor.defaults.subtensor._mock)
- # registration args. Used for register and re-register and anything that calls register.
- parser.add_argument('--' + prefix_str + 'subtensor.register.num_processes', '-n', dest=prefix_str + 'subtensor.register.num_processes', help="Number of processors to use for registration", type=int, default=bittensor.defaults.subtensor.register.num_processes)
- parser.add_argument('--' + prefix_str + 'subtensor.register.update_interval', '--' + prefix_str + 'subtensor.register.cuda.update_interval', '--' + prefix_str + 'cuda.update_interval', '-u', help="The number of nonces to process before checking for next block during registration", type=int, default=bittensor.defaults.subtensor.register.update_interval)
- parser.add_argument('--' + prefix_str + 'subtensor.register.no_output_in_place', '--' + prefix_str + 'no_output_in_place', dest="subtensor.register.output_in_place", help="Whether to not ouput the registration statistics in-place. Set flag to disable output in-place.", action='store_false', required=False, default=bittensor.defaults.subtensor.register.output_in_place)
- parser.add_argument('--' + prefix_str + 'subtensor.register.verbose', help="Whether to ouput the registration statistics verbosely.", action='store_true', required=False, default=bittensor.defaults.subtensor.register.verbose)
-
- ## Registration args for CUDA registration.
- parser.add_argument( '--' + prefix_str + 'subtensor.register.cuda.use_cuda', '--' + prefix_str + 'cuda', '--' + prefix_str + 'cuda.use_cuda', default=argparse.SUPPRESS, help='''Set flag to use CUDA to register.''', action="store_true", required=False )
- parser.add_argument( '--' + prefix_str + 'subtensor.register.cuda.no_cuda', '--' + prefix_str + 'no_cuda', '--' + prefix_str + 'cuda.no_cuda', dest=prefix_str + 'subtensor.register.cuda.use_cuda', default=argparse.SUPPRESS, help='''Set flag to not use CUDA for registration''', action="store_false", required=False )
-
- parser.add_argument( '--' + prefix_str + 'subtensor.register.cuda.dev_id', '--' + prefix_str + 'cuda.dev_id', type=int, nargs='+', default=argparse.SUPPRESS, help='''Set the CUDA device id(s). Goes by the order of speed. (i.e. 0 is the fastest).''', required=False )
- parser.add_argument( '--' + prefix_str + 'subtensor.register.cuda.TPB', '--' + prefix_str + 'cuda.TPB', type=int, default=bittensor.defaults.subtensor.register.cuda.TPB, help='''Set the number of Threads Per Block for CUDA.''', required=False )
-
- parser.add_argument('--netuid', type=int, help='netuid for subnet to serve this neuron on', default=argparse.SUPPRESS)
- except argparse.ArgumentError:
- # re-parsing arguments.
- pass
-
- @classmethod
- def add_defaults(cls, defaults ):
- """ Adds parser defaults to object from enviroment variables.
- """
- defaults.subtensor = bittensor.Config()
- defaults.subtensor.network = os.getenv('BT_SUBTENSOR_NETWORK') if os.getenv('BT_SUBTENSOR_NETWORK') != None else 'finney'
- defaults.subtensor.chain_endpoint = os.getenv('BT_SUBTENSOR_CHAIN_ENDPOINT') if os.getenv('BT_SUBTENSOR_CHAIN_ENDPOINT') != None else None
- defaults.subtensor._mock = os.getenv('BT_SUBTENSOR_MOCK') if os.getenv('BT_SUBTENSOR_MOCK') != None else False
-
- defaults.subtensor.register = bittensor.Config()
- defaults.subtensor.register.num_processes = os.getenv('BT_SUBTENSOR_REGISTER_NUM_PROCESSES') if os.getenv('BT_SUBTENSOR_REGISTER_NUM_PROCESSES') != None else None # uses processor count by default within the function
- defaults.subtensor.register.update_interval = os.getenv('BT_SUBTENSOR_REGISTER_UPDATE_INTERVAL') if os.getenv('BT_SUBTENSOR_REGISTER_UPDATE_INTERVAL') != None else 50_000
- defaults.subtensor.register.output_in_place = True
- defaults.subtensor.register.verbose = False
-
- defaults.subtensor.register.cuda = bittensor.Config()
- defaults.subtensor.register.cuda.dev_id = [0]
- defaults.subtensor.register.cuda.use_cuda = False
- defaults.subtensor.register.cuda.TPB = 256
-
-
-
- @staticmethod
- def check_config( config: 'bittensor.Config' ):
- assert config.subtensor
- #assert config.subtensor.network != None
- if config.subtensor.get('register') and config.subtensor.register.get('cuda'):
- assert all((isinstance(x, int) or isinstance(x, str) and x.isnumeric() ) for x in config.subtensor.register.cuda.get('dev_id', []))
-
- if config.subtensor.register.cuda.get('use_cuda', bittensor.defaults.subtensor.register.cuda.use_cuda):
- try:
- import cubit
- except ImportError:
- raise ImportError('CUDA registration is enabled but cubit is not installed. Please install cubit.')
-
- if not is_cuda_available():
- raise RuntimeError('CUDA registration is enabled but no CUDA devices are detected.')
-
-
- @staticmethod
- def determine_chain_endpoint(network: str):
-
- if network == "finney":
- # Kiru Finney stagin network.
- return bittensor.__finney_entrypoint__
- elif network == "nobunaga":
- # Staging network.
- return bittensor.__nobunaga_entrypoint__
- elif network == "bellagene":
- # Parachain test net
- return bittensor.__bellagene_entrypoint__
- elif network == "local":
- # Local chain.
- return bittensor.__local_entrypoint__
- elif network == 'mock':
- return bittensor.__mock_entrypoint__
- else:
- return bittensor.__local_entrypoint__
diff --git a/commune/modules/bittensor/subtensor/chain_data.py b/commune/modules/bittensor/subtensor/chain_data.py
deleted file mode 100644
index da11fd300..000000000
--- a/commune/modules/bittensor/subtensor/chain_data.py
+++ /dev/null
@@ -1,660 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-from dataclasses import dataclass
-from typing import List, Tuple, Dict, Optional, Any
-import bittensor
-from bittensor import Balance
-import torch
-from scalecodec.base import RuntimeConfiguration, ScaleBytes
-from scalecodec.type_registry import load_type_registry_preset
-from scalecodec.utils.ss58 import ss58_encode
-from enum import Enum
-
-
-custom_rpc_type_registry = {
- "types": {
- "SubnetInfo": {
- "type": "struct",
- "type_mapping": [
- ["netuid", "Compact"],
- ["rho", "Compact"],
- ["kappa", "Compact"],
- ["difficulty", "Compact"],
- ["immunity_period", "Compact"],
- ["validator_batch_size", "Compact"],
- ["validator_sequence_length", "Compact"],
- ["validator_epochs_per_reset", "Compact"],
- ["validator_epoch_length", "Compact"],
- ["max_allowed_validators", "Compact"],
- ["min_allowed_weights", "Compact"],
- ["max_weights_limit", "Compact"],
- ["scaling_law_power", "Compact"],
- ["synergy_scaling_law_power", "Compact"],
- ["subnetwork_n", "Compact"],
- ["max_allowed_uids", "Compact"],
- ["blocks_since_last_step", "Compact"],
- ["tempo", "Compact"],
- ["network_modality", "Compact"],
- ["network_connect", "Vec<[u16; 2]>"],
- ["emission_values", "Compact"],
- ["burn", "Compact"],
- ]
- },
- "DelegateInfo": {
- "type": "struct",
- "type_mapping": [
- ["delegate_ss58", "AccountId"],
- ["take", "Compact"],
- ["nominators", "Vec<(AccountId, Compact)>"],
- ["owner_ss58", "AccountId"],
- ["registrations", "Vec>"],
- ["validator_permits", "Vec>"],
- ["return_per_1000", "Compact"],
- ["total_daily_return", "Compact"],
- ],
- },
- "NeuronInfo": {
- "type": "struct",
- "type_mapping": [
- ["hotkey", "AccountId"],
- ["coldkey", "AccountId"],
- ["uid", "Compact"],
- ["netuid", "Compact"],
- ["active", "bool"],
- ["axon_info", "AxonInfo"],
- ["prometheus_info", "PrometheusInfo"],
- ["stake", "Vec<(AccountId, Compact)>"],
- ["rank", "Compact"],
- ["emission", "Compact"],
- ["incentive", "Compact"],
- ["consensus", "Compact"],
- ["trust", "Compact"],
- ["validator_trust", "Compact"],
- ["dividends", "Compact"],
- ["last_update", "Compact"],
- ["validator_permit", "bool"],
- ["weights", "Vec<(Compact, Compact)>"],
- ["bonds", "Vec<(Compact, Compact)>"],
- ["pruning_score", "Compact"]
- ],
- },
- "NeuronInfoLite": {
- "type": "struct",
- "type_mapping": [
- ["hotkey", "AccountId"],
- ["coldkey", "AccountId"],
- ["uid", "Compact"],
- ["netuid", "Compact"],
- ["active", "bool"],
- ["axon_info", "AxonInfo"],
- ["prometheus_info", "PrometheusInfo"],
- ["stake", "Vec<(AccountId, Compact)>"],
- ["rank", "Compact"],
- ["emission", "Compact"],
- ["incentive", "Compact"],
- ["consensus", "Compact"],
- ["trust", "Compact"],
- ["validator_trust", "Compact"],
- ["dividends", "Compact"],
- ["last_update", "Compact"],
- ["validator_permit", "bool"],
- ["pruning_score", "Compact"]
- ],
- },
- "AxonInfo": {
- "type": "struct",
- "type_mapping": [
- ["block", "u64"],
- ["version", "u32"],
- ["ip", "u128"],
- ["port", "u16"],
- ["ip_type", "u8"],
- ["protocol", "u8"],
- ["placeholder1", "u8"],
- ["placeholder2", "u8"],
- ],
- },
- "PrometheusInfo": {
- "type": "struct",
- "type_mapping": [
- ["block", "u64"],
- ["version", "u32"],
- ["ip", "u128"],
- ["port", "u16"],
- ["ip_type", "u8"],
- ],
- },
- }
-}
-
-class ChainDataType(Enum):
- NeuronInfo = 1
- SubnetInfo = 2
- DelegateInfo = 3
- NeuronInfoLite = 4
- DelegatedInfo = 5
-
-# Constants
-RAOPERTAO = 1e9
-U16_MAX = 65535
-U64_MAX = 18446744073709551615
-
-def from_scale_encoding( vec_u8: List[int], type_name: ChainDataType, is_vec: bool = False, is_option: bool = False ) -> Optional[Dict]:
- as_bytes = bytes(vec_u8)
- as_scale_bytes = ScaleBytes(as_bytes)
- rpc_runtime_config = RuntimeConfiguration()
- rpc_runtime_config.update_type_registry(load_type_registry_preset("legacy"))
- rpc_runtime_config.update_type_registry(custom_rpc_type_registry)
-
- type_string = type_name.name
- if type_name == ChainDataType.DelegatedInfo:
- # DelegatedInfo is a tuple of (DelegateInfo, Compact)
- type_string = f'({ChainDataType.DelegateInfo.name}, Compact)'
- if is_option:
- type_string = f'Option<{type_string}>'
- if is_vec:
- type_string = f'Vec<{type_string}>'
-
- obj = rpc_runtime_config.create_scale_object(
- type_string,
- data=as_scale_bytes
- )
-
- return obj.decode()
-
-# Dataclasses for chain data.
-@dataclass
-class NeuronInfo:
- r"""
- Dataclass for neuron metadata.
- """
- hotkey: str
- coldkey: str
- uid: int
- netuid: int
- active: int
- stake: Balance
- # mapping of coldkey to amount staked to this Neuron
- stake_dict: Dict[str, Balance]
- total_stake: Balance
- rank: float
- emission: float
- incentive: float
- consensus: float
- trust: float
- validator_trust: float
- dividends: float
- last_update: int
- validator_permit: bool
- weights: List[List[int]]
- bonds: List[List[int]]
- prometheus_info: 'PrometheusInfo'
- axon_info: 'AxonInfo'
- pruning_score: int
- is_null: bool = False
-
- @classmethod
- def fix_decoded_values(cls, neuron_info_decoded: Any) -> 'NeuronInfo':
- r""" Fixes the values of the NeuronInfo object.
- """
- neuron_info_decoded['hotkey'] = ss58_encode(neuron_info_decoded['hotkey'], bittensor.__ss58_format__)
- neuron_info_decoded['coldkey'] = ss58_encode(neuron_info_decoded['coldkey'], bittensor.__ss58_format__)
- stake_dict = { ss58_encode( coldkey, bittensor.__ss58_format__): bittensor.Balance.from_rao(int(stake)) for coldkey, stake in neuron_info_decoded['stake'] }
- neuron_info_decoded['stake_dict'] = stake_dict
- neuron_info_decoded['stake'] = sum(stake_dict.values())
- neuron_info_decoded['total_stake'] = neuron_info_decoded['stake']
- neuron_info_decoded['weights'] = [[int(weight[0]), int(weight[1])] for weight in neuron_info_decoded['weights']]
- neuron_info_decoded['bonds'] = [[int(bond[0]), int(bond[1])] for bond in neuron_info_decoded['bonds']]
- neuron_info_decoded['rank'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['rank'])
- neuron_info_decoded['emission'] = neuron_info_decoded['emission'] / RAOPERTAO
- neuron_info_decoded['incentive'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['incentive'])
- neuron_info_decoded['consensus'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['consensus'])
- neuron_info_decoded['trust'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['trust'])
- neuron_info_decoded['validator_trust'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['validator_trust'])
- neuron_info_decoded['dividends'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['dividends'])
- neuron_info_decoded['prometheus_info'] = PrometheusInfo.fix_decoded_values(neuron_info_decoded['prometheus_info'])
- neuron_info_decoded['axon_info'] = AxonInfo.fix_decoded_values(neuron_info_decoded['axon_info'])
-
- return cls(**neuron_info_decoded)
-
- @classmethod
- def from_vec_u8(cls, vec_u8: List[int]) -> 'NeuronInfo':
- r""" Returns a NeuronInfo object from a vec_u8.
- """
- if len(vec_u8) == 0:
- return NeuronInfo._null_neuron()
-
- decoded = from_scale_encoding(vec_u8, ChainDataType.NeuronInfo)
- if decoded is None:
- return NeuronInfo._null_neuron()
-
- decoded = NeuronInfo.fix_decoded_values(decoded)
-
- return decoded
-
- @classmethod
- def list_from_vec_u8(cls, vec_u8: List[int]) -> List['NeuronInfo']:
- r""" Returns a list of NeuronInfo objects from a vec_u8.
- """
-
- decoded_list = from_scale_encoding(vec_u8, ChainDataType.NeuronInfo, is_vec=True)
- if decoded_list is None:
- return []
-
- decoded_list = [NeuronInfo.fix_decoded_values(decoded) for decoded in decoded_list]
- return decoded_list
-
-
- @staticmethod
- def _null_neuron() -> 'NeuronInfo':
- neuron = NeuronInfo(
- uid = 0,
- netuid = 0,
- active = 0,
- stake = Balance.from_rao(0),
- stake_dict = {},
- total_stake = Balance.from_rao(0),
- rank = 0,
- emission = 0,
- incentive = 0,
- consensus = 0,
- trust = 0,
- validator_trust = 0,
- dividends = 0,
- last_update = 0,
- validator_permit = False,
- weights = [],
- bonds = [],
- prometheus_info = None,
- axon_info = None,
- is_null = True,
- coldkey = "000000000000000000000000000000000000000000000000",
- hotkey = "000000000000000000000000000000000000000000000000",
- pruning_score = 0,
- )
- return neuron
-
- @staticmethod
- def _neuron_dict_to_namespace(neuron_dict) -> 'NeuronInfo':
- # TODO: Legacy: remove?
- if neuron_dict['hotkey'] == '5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM':
- return NeuronInfo._null_neuron()
- else:
- neuron = NeuronInfo( **neuron_dict )
- neuron.stake = Balance.from_rao(neuron.total_stake)
- neuron.stake_dict = { hk: Balance.from_rao(stake) for hk, stake in neuron.stake.items() }
- neuron.total_stake = neuron.stake
- neuron.rank = neuron.rank / U16_MAX
- neuron.trust = neuron.trust / U16_MAX
- neuron.consensus = neuron.consensus / U16_MAX
- neuron.validator_trust = neuron.validator_trust / U16_MAX
- neuron.incentive = neuron.incentive / U16_MAX
- neuron.dividends = neuron.dividends / U16_MAX
- neuron.emission = neuron.emission / RAOPERTAO
-
- return neuron
-
-@dataclass
-class NeuronInfoLite:
- r"""
- Dataclass for neuron metadata, but without the weights and bonds.
- """
- hotkey: str
- coldkey: str
- uid: int
- netuid: int
- active: int
- stake: Balance
- # mapping of coldkey to amount staked to this Neuron
- stake_dict: Dict[str, Balance]
- total_stake: Balance
- rank: float
- emission: float
- incentive: float
- consensus: float
- trust: float
- validator_trust: float
- dividends: float
- last_update: int
- validator_permit: bool
- #weights: List[List[int]]
- #bonds: List[List[int]] No weights or bonds in lite version
- prometheus_info: 'PrometheusInfo'
- axon_info: 'AxonInfo'
- pruning_score: int
- is_null: bool = False
-
- @classmethod
- def fix_decoded_values(cls, neuron_info_decoded: Any) -> 'NeuronInfoLite':
- r""" Fixes the values of the NeuronInfoLite object.
- """
- neuron_info_decoded['hotkey'] = ss58_encode(neuron_info_decoded['hotkey'], bittensor.__ss58_format__)
- neuron_info_decoded['coldkey'] = ss58_encode(neuron_info_decoded['coldkey'], bittensor.__ss58_format__)
- stake_dict = { ss58_encode( coldkey, bittensor.__ss58_format__): bittensor.Balance.from_rao(int(stake)) for coldkey, stake in neuron_info_decoded['stake'] }
- neuron_info_decoded['stake_dict'] = stake_dict
- neuron_info_decoded['stake'] = sum(stake_dict.values())
- neuron_info_decoded['total_stake'] = neuron_info_decoded['stake']
- # Don't need weights and bonds in lite version
- #neuron_info_decoded['weights'] = [[int(weight[0]), int(weight[1])] for weight in neuron_info_decoded['weights']]
- #neuron_info_decoded['bonds'] = [[int(bond[0]), int(bond[1])] for bond in neuron_info_decoded['bonds']]
- neuron_info_decoded['rank'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['rank'])
- neuron_info_decoded['emission'] = neuron_info_decoded['emission'] / RAOPERTAO
- neuron_info_decoded['incentive'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['incentive'])
- neuron_info_decoded['consensus'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['consensus'])
- neuron_info_decoded['trust'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['trust'])
- neuron_info_decoded['validator_trust'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['validator_trust'])
- neuron_info_decoded['dividends'] = bittensor.utils.U16_NORMALIZED_FLOAT(neuron_info_decoded['dividends'])
- neuron_info_decoded['prometheus_info'] = PrometheusInfo.fix_decoded_values(neuron_info_decoded['prometheus_info'])
- neuron_info_decoded['axon_info'] = AxonInfo.fix_decoded_values(neuron_info_decoded['axon_info'])
-
- return cls(**neuron_info_decoded)
-
- @classmethod
- def from_vec_u8(cls, vec_u8: List[int]) -> 'NeuronInfoLite':
- r""" Returns a NeuronInfoLite object from a vec_u8.
- """
- if len(vec_u8) == 0:
- return NeuronInfoLite._null_neuron()
-
- decoded = from_scale_encoding(vec_u8, ChainDataType.NeuronInfoLite)
- if decoded is None:
- return NeuronInfoLite._null_neuron()
-
- decoded = NeuronInfoLite.fix_decoded_values(decoded)
-
- return decoded
-
- @classmethod
- def list_from_vec_u8(cls, vec_u8: List[int]) -> List['NeuronInfoLite']:
- r""" Returns a list of NeuronInfoLite objects from a vec_u8.
- """
-
- decoded_list = from_scale_encoding(vec_u8, ChainDataType.NeuronInfoLite, is_vec=True)
- if decoded_list is None:
- return []
-
- decoded_list = [NeuronInfoLite.fix_decoded_values(decoded) for decoded in decoded_list]
- return decoded_list
-
-
- @staticmethod
- def _null_neuron() -> 'NeuronInfoLite':
- neuron = NeuronInfoLite(
- uid = 0,
- netuid = 0,
- active = 0,
- stake = Balance.from_rao(0),
- stake_dict = {},
- total_stake = Balance.from_rao(0),
- rank = 0,
- emission = 0,
- incentive = 0,
- consensus = 0,
- trust = 0,
- validator_trust = 0,
- dividends = 0,
- last_update = 0,
- validator_permit = False,
- #weights = [], // No weights or bonds in lite version
- #bonds = [],
- prometheus_info = None,
- axon_info = None,
- is_null = True,
- coldkey = "000000000000000000000000000000000000000000000000",
- hotkey = "000000000000000000000000000000000000000000000000",
- pruning_score = 0,
- )
- return neuron
-
- @staticmethod
- def _neuron_dict_to_namespace(neuron_dict) -> 'NeuronInfoLite':
- # TODO: Legacy: remove?
- if neuron_dict['hotkey'] == '5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM':
- return NeuronInfoLite._null_neuron()
- else:
- neuron = NeuronInfoLite( **neuron_dict )
- neuron.stake = Balance.from_rao(neuron.total_stake)
- neuron.stake_dict = { hk: Balance.from_rao(stake) for hk, stake in neuron.stake.items() }
- neuron.total_stake = neuron.stake
- neuron.rank = neuron.rank / U16_MAX
- neuron.trust = neuron.trust / U16_MAX
- neuron.consensus = neuron.consensus / U16_MAX
- neuron.validator_trust = neuron.validator_trust / U16_MAX
- neuron.incentive = neuron.incentive / U16_MAX
- neuron.dividends = neuron.dividends / U16_MAX
- neuron.emission = neuron.emission / RAOPERTAO
-
- return neuron
-
-@dataclass
-class AxonInfo:
- r"""
- Dataclass for axon info.
- """
- block: int
- version: int
- ip: str
- port: int
- ip_type: int
- protocol: int
- placeholder1: int # placeholder for future use
- placeholder2: int
-
- @classmethod
- def fix_decoded_values(cls, axon_info_decoded: Dict) -> 'AxonInfo':
- r""" Returns an AxonInfo object from an axon_info_decoded dictionary.
- """
- axon_info_decoded['ip'] = bittensor.utils.networking.int_to_ip(int(axon_info_decoded['ip']))
-
- return cls(**axon_info_decoded)
-
-@dataclass
-class PrometheusInfo:
- r"""
- Dataclass for prometheus info.
- """
- block: int
- version: int
- ip: str
- port: int
- ip_type: int
-
- @classmethod
- def fix_decoded_values(cls, prometheus_info_decoded: Dict) -> 'PrometheusInfo':
- r""" Returns a PrometheusInfo object from a prometheus_info_decoded dictionary.
- """
- prometheus_info_decoded['ip'] = bittensor.utils.networking.int_to_ip(int(prometheus_info_decoded['ip']))
-
- return cls(**prometheus_info_decoded)
-@dataclass
-class DelegateInfo:
- r"""
- Dataclass for delegate info.
- """
- hotkey_ss58: str # Hotkey of delegate
- total_stake: Balance # Total stake of the delegate
- nominators: List[Tuple[str, Balance]] # List of nominators of the delegate and their stake
- owner_ss58: str # Coldkey of owner
- take: float # Take of the delegate as a percentage
- validator_permits: List[int] # List of subnets that the delegate is allowed to validate on
- registrations: List[int] # List of subnets that the delegate is registered on
- return_per_1000: bittensor.Balance # Return per 1000 tao of the delegate over a day
- total_daily_return: bittensor.Balance # Total daily return of the delegate
-
- @classmethod
- def fix_decoded_values(cls, decoded: Any) -> 'DelegateInfo':
- r""" Fixes the decoded values.
- """
-
- return cls(
- hotkey_ss58 = ss58_encode(decoded['delegate_ss58'], bittensor.__ss58_format__),
- owner_ss58 = ss58_encode(decoded['owner_ss58'], bittensor.__ss58_format__),
- take = bittensor.utils.U16_NORMALIZED_FLOAT(decoded['take']),
- nominators = [
- (ss58_encode(nom[0], bittensor.__ss58_format__), Balance.from_rao(nom[1]))
- for nom in decoded['nominators']
- ],
- total_stake = Balance.from_rao(sum([nom[1] for nom in decoded['nominators']])),
- validator_permits = decoded['validator_permits'],
- registrations = decoded['registrations'],
- return_per_1000 = bittensor.Balance.from_rao(decoded['return_per_1000']),
- total_daily_return = bittensor.Balance.from_rao(decoded['total_daily_return']),
- )
-
- @classmethod
- def from_vec_u8(cls, vec_u8: List[int]) -> Optional['DelegateInfo']:
- r""" Returns a DelegateInfo object from a vec_u8.
- """
- if len(vec_u8) == 0:
- return None
-
- decoded = from_scale_encoding(vec_u8, ChainDataType.DelegateInfo)
-
- if decoded is None:
- return None
-
- decoded = DelegateInfo.fix_decoded_values(decoded)
-
- return decoded
-
- @classmethod
- def list_from_vec_u8(cls, vec_u8: List[int]) -> List['DelegateInfo']:
- r""" Returns a list of DelegateInfo objects from a vec_u8.
- """
- decoded = from_scale_encoding(vec_u8, ChainDataType.DelegateInfo, is_vec=True)
-
- if decoded is None:
- return []
-
- decoded = [DelegateInfo.fix_decoded_values(d) for d in decoded]
-
- return decoded
-
- @classmethod
- def delegated_list_from_vec_u8(cls, vec_u8: List[int]) -> List[Tuple['DelegateInfo', Balance]]:
- r""" Returns a list of Tuples of DelegateInfo objects, and Balance, from a vec_u8.
- This is the list of delegates that the user has delegated to, and the amount of stake delegated.
- """
- decoded = from_scale_encoding(vec_u8, ChainDataType.DelegatedInfo, is_vec=True)
-
- if decoded is None:
- return []
-
- decoded = [(DelegateInfo.fix_decoded_values(d), Balance.from_rao(s)) for d, s in decoded]
-
- return decoded
-
-@dataclass
-class SubnetInfo:
- r"""
- Dataclass for subnet info.
- """
- netuid: int
- rho: int
- kappa: int
- difficulty: int
- immunity_period: int
- validator_batch_size: int
- validator_sequence_length: int
- validator_epochs_per_reset: int
- validator_epoch_length: int
- max_allowed_validators: int
- min_allowed_weights: int
- max_weight_limit: float
- scaling_law_power: float
- synergy_scaling_law_power: float
- subnetwork_n: int
- max_n: int
- blocks_since_epoch: int
- tempo: int
- modality: int
- # netuid -> topk percentile prunning score requirement (u16:MAX normalized.)
- connection_requirements: Dict[str, float]
- emission_value: float
- burn: Balance
-
- @classmethod
- def from_vec_u8(cls, vec_u8: List[int]) -> Optional['SubnetInfo']:
- r""" Returns a SubnetInfo object from a vec_u8.
- """
- if len(vec_u8) == 0:
- return None
-
- decoded = from_scale_encoding(vec_u8, ChainDataType.SubnetInfo)
-
- if decoded is None:
- return None
-
- return SubnetInfo.fix_decoded_values(decoded)
-
- @classmethod
- def list_from_vec_u8(cls, vec_u8: List[int]) -> List['SubnetInfo']:
- r""" Returns a list of SubnetInfo objects from a vec_u8.
- """
- decoded = from_scale_encoding(vec_u8, ChainDataType.SubnetInfo, is_vec=True, is_option=True)
-
- if decoded is None:
- return []
-
- decoded = [SubnetInfo.fix_decoded_values(d) for d in decoded]
-
- return decoded
-
- @classmethod
- def fix_decoded_values(cls, decoded: Dict) -> 'SubnetInfo':
- r""" Returns a SubnetInfo object from a decoded SubnetInfo dictionary.
- """
- return SubnetInfo(
- netuid = decoded['netuid'],
- rho = decoded['rho'],
- kappa = decoded['kappa'],
- difficulty = decoded['difficulty'],
- immunity_period = decoded['immunity_period'],
- validator_batch_size = decoded['validator_batch_size'],
- validator_sequence_length = decoded['validator_sequence_length'],
- validator_epochs_per_reset = decoded['validator_epochs_per_reset'],
- validator_epoch_length = decoded['validator_epoch_length'],
- max_allowed_validators = decoded['max_allowed_validators'],
- min_allowed_weights = decoded['min_allowed_weights'],
- max_weight_limit = decoded['max_weights_limit'],
- scaling_law_power = decoded['scaling_law_power'],
- synergy_scaling_law_power= decoded['synergy_scaling_law_power'],
- subnetwork_n = decoded['subnetwork_n'],
- max_n = decoded['max_allowed_uids'],
- blocks_since_epoch = decoded['blocks_since_last_step'],
- tempo = decoded['tempo'],
- modality = decoded['network_modality'],
- connection_requirements = {
- str(int(netuid)): bittensor.utils.U16_NORMALIZED_FLOAT(int(req)) for netuid, req in decoded['network_connect']
- },
- emission_value= decoded['emission_values'],
- burn = Balance(0)#Balance.from_rao(decoded['burn'])
- )
-
- def to_parameter_dict( self ) -> 'torch.nn.ParameterDict':
- r""" Returns a torch tensor of the subnet info.
- """
- return torch.nn.ParameterDict(
- self.__dict__
- )
-
- @classmethod
- def from_parameter_dict( cls, parameter_dict: 'torch.nn.ParameterDict' ) -> 'SubnetInfo':
- r""" Returns a SubnetInfo object from a torch parameter_dict.
- """
- return cls( **dict(parameter_dict) )
diff --git a/commune/modules/bittensor/subtensor/errors.py b/commune/modules/bittensor/subtensor/errors.py
deleted file mode 100644
index c81c959e9..000000000
--- a/commune/modules/bittensor/subtensor/errors.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-class ChainError(BaseException):
- r""" Base error for any chain related errors.
- """
- pass
-
-
-class ChainConnectionError(ChainError):
- r""" Error for any chain connection related errors.
- """
- pass
-
-
-class ChainTransactionError(ChainError):
- r""" Error for any chain transaction related errors.
- """
- pass
-
-
-class ChainQueryError(ChainError):
- r""" Error for any chain query related errors.
- """
- pass
-
-
-class StakeError(ChainTransactionError):
- r""" Error raised when a stake transaction fails.
- """
- pass
-
-
-class UnstakeError(ChainTransactionError):
- r""" Error raised when an unstake transaction fails.
- """
- pass
-
-
-class TransferError(ChainTransactionError):
- r""" Error raised when a transfer transaction fails.
- """
- pass
-
-
-class RegistrationError(ChainTransactionError):
- r""" Error raised when a neuron registration transaction fails.
- """
- pass
-
-
-class NotRegisteredError(ChainTransactionError):
- r""" Error raised when a neuron is not registered, and the transaction requires it to be.
- """
- pass
-
-
-class NotDelegateError(StakeError):
- r""" Error raised when a hotkey you are trying to stake to is not a delegate.
- """
- pass
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/__init__.py b/commune/modules/bittensor/subtensor/extrinsics/__init__.py
deleted file mode 100644
index 222ffa665..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/delegation.py b/commune/modules/bittensor/subtensor/extrinsics/delegation.py
deleted file mode 100644
index e976f0e33..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/delegation.py
+++ /dev/null
@@ -1,366 +0,0 @@
-
-
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-from ..errors import *
-from rich.prompt import Confirm
-from typing import List, Dict, Union, Optional
-from bittensor.utils.balance import Balance
-from .staking import __do_add_stake_single
-
-from loguru import logger
-logger = logger.opt(colors=True)
-
-def nominate_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.Wallet',
- wait_for_finalization: bool = False,
- wait_for_inclusion: bool = True
-) -> bool:
- r""" Becomes a delegate for the hotkey.
- Args:
- wallet ( bittensor.Wallet ):
- The wallet to become a delegate for.
- Returns:
- success (bool):
- True if the transaction was successful.
- """
- # Unlock the coldkey.
- wallet.coldkey
- wallet.hotkey
-
- # Check if the hotkey is already a delegate.
- if subtensor.is_hotkey_delegate( wallet.hotkey.ss58_address ):
- logger.error('Hotkey {} is already a delegate.'.format(wallet.hotkey.ss58_address))
- return False
-
- with bittensor.__console__.status(":satellite: Sending nominate call on [white]{}[/white] ...".format(subtensor.network)):
- try:
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='become_delegate',
- call_params = {
- 'hotkey': wallet.hotkey.ss58_address
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey ) # sign with coldkey
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- response.process_events()
- if response.is_success:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- bittensor.logging.success( prefix = 'Become Delegate', sufix = 'Finalized: ' + str(response.is_success) )
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
- bittensor.logging.warning( prefix = 'Set weights', sufix = 'Failed: ' + str(response.error_message) )
-
- except Exception as e:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(e))
- bittensor.logging.warning( prefix = 'Set weights', sufix = 'Failed: ' + str(e) )
- return False
-
- if response.is_success:
- return True
-
- return False
-
-def do_delegation(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- delegate_ss58: str,
- amount: 'bittensor.Balance',
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- ) -> bool:
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='add_stake',
- call_params={
- 'hotkey': delegate_ss58,
- 'amount_staked': amount.rao
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- return True
- response.process_events()
- if response.is_success:
- return True
- else:
- raise StakeError(response.error_message)
-
-def do_undelegation(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- delegate_ss58: str,
- amount: 'bittensor.Balance',
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- ) -> bool:
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='remove_stake',
- call_params={
- 'hotkey': delegate_ss58,
- 'amount_unstaked': amount.rao
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- return True
- response.process_events()
- if response.is_success:
- return True
- else:
- raise StakeError(response.error_message)
-
-
-def delegate_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- delegate_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- r""" Delegates the specified amount of stake to the passed delegate.
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object.
- delegate_ss58 (Optional[str]):
- ss58 address of the delegate.
- amount (Union[Balance, float]):
- Amount to stake as bittensor balance, or float interpreted as Tao.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
-
- Raises:
- NotRegisteredError:
- If the wallet is not registered on the chain.
- NotDelegateError:
- If the hotkey is not a delegate on the chain.
- """
- # Decrypt keys,
- wallet.coldkey
- if not subtensor.is_hotkey_delegate( delegate_ss58 ):
- raise NotDelegateError("Hotkey: {} is not a delegate.".format( delegate_ss58 ))
-
- # Get state.
- my_prev_coldkey_balance = subtensor.get_balance( wallet.coldkey.ss58_address )
- delegate_take = subtensor.get_delegate_take( delegate_ss58 )
- delegate_owner = subtensor.get_hotkey_owner( delegate_ss58 )
- my_prev_delegated_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = delegate_ss58 )
-
- # Convert to bittensor.Balance
- if amount == None:
- # Stake it all.
- staking_balance = bittensor.Balance.from_tao( my_prev_coldkey_balance.tao )
- elif not isinstance(amount, bittensor.Balance ):
- staking_balance = bittensor.Balance.from_tao( amount )
- else:
- staking_balance = amount
-
- # Remove existential balance to keep key alive.
- if staking_balance > bittensor.Balance.from_rao( 1000 ):
- staking_balance = staking_balance - bittensor.Balance.from_rao( 1000 )
- else:
- staking_balance = staking_balance
-
- # Check enough balance to stake.
- if staking_balance > my_prev_coldkey_balance:
- bittensor.__console__.print(":cross_mark: [red]Not enough balance[/red]:[bold white]\n balance:{}\n amount: {}\n coldkey: {}[/bold white]".format(my_prev_coldkey_balance, staking_balance, wallet.name))
- return False
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to delegate:[bold white]\n amount: {}\n to: {}\n owner: {}[/bold white]".format( staking_balance, delegate_ss58, delegate_owner) ):
- return False
-
- try:
- with bittensor.__console__.status(":satellite: Staking to: [bold white]{}[/bold white] ...".format(subtensor.network)):
- staking_response: bool = do_delegation(
- subtensor = subtensor,
- wallet = wallet,
- delegate_ss58 = delegate_ss58,
- amount = staking_balance,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- )
-
- if staking_response: # If we successfully staked.
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- with bittensor.__console__.status(":satellite: Checking Balance on: [white]{}[/white] ...".format(subtensor.network)):
- new_balance = subtensor.get_balance( address = wallet.coldkey.ss58_address )
- block = subtensor.get_current_block()
- new_delegate_stake = subtensor.get_stake_for_coldkey_and_hotkey(
- coldkey_ss58 = wallet.coldkeypub.ss58_address,
- hotkey_ss58 = delegate_ss58,
- block=block
- ) # Get current stake
-
- bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( my_prev_coldkey_balance, new_balance ))
- bittensor.__console__.print("Stake:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( my_prev_delegated_stake, new_delegate_stake ))
- return True
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
- return False
-
- except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(wallet.hotkey_str))
- return False
- except StakeError as e:
- bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
- return False
-
-def undelegate_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- delegate_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- r""" Un-delegates stake from the passed delegate.
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object.
- delegate_ss58 (Optional[str]):
- ss58 address of the delegate.
- amount (Union[Balance, float]):
- Amount to unstake as bittensor balance, or float interpreted as Tao.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
-
- Raises:
- NotRegisteredError:
- If the wallet is not registered on the chain.
- NotDelegateError:
- If the hotkey is not a delegate on the chain.
- """
- # Decrypt keys,
- wallet.coldkey
- if not subtensor.is_hotkey_delegate( delegate_ss58 ):
- raise NotDelegateError("Hotkey: {} is not a delegate.".format( delegate_ss58 ))
-
- # Get state.
- my_prev_coldkey_balance = subtensor.get_balance( wallet.coldkey.ss58_address )
- delegate_take = subtensor.get_delegate_take( delegate_ss58 )
- delegate_owner = subtensor.get_hotkey_owner( delegate_ss58 )
- my_prev_delegated_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = delegate_ss58 )
-
- # Convert to bittensor.Balance
- if amount == None:
- # Stake it all.
- unstaking_balance = bittensor.Balance.from_tao( my_prev_delegated_stake.tao )
-
- elif not isinstance(amount, bittensor.Balance ):
- unstaking_balance = bittensor.Balance.from_tao( amount )
-
- else:
- unstaking_balance = amount
-
- # Check enough stake to unstake.
- if unstaking_balance > my_prev_delegated_stake:
- bittensor.__console__.print(":cross_mark: [red]Not enough delegated stake[/red]:[bold white]\n stake:{}\n amount: {}\n coldkey: {}[/bold white]".format(my_prev_delegated_stake, unstaking_balance, wallet.name))
- return False
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to un-delegate:[bold white]\n amount: {}\n from: {}\n owner: {}[/bold white]".format( unstaking_balance, delegate_ss58, delegate_owner) ):
- return False
-
- try:
- with bittensor.__console__.status(":satellite: Unstaking from: [bold white]{}[/bold white] ...".format(subtensor.network)):
- staking_response: bool = do_undelegation(
- subtensor = subtensor,
- wallet = wallet,
- delegate_ss58 = delegate_ss58,
- amount = unstaking_balance,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- )
-
- if staking_response: # If we successfully staked.
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- with bittensor.__console__.status(":satellite: Checking Balance on: [white]{}[/white] ...".format(subtensor.network)):
- new_balance = subtensor.get_balance( address = wallet.coldkey.ss58_address )
- block = subtensor.get_current_block()
- new_delegate_stake = subtensor.get_stake_for_coldkey_and_hotkey(
- coldkey_ss58 = wallet.coldkeypub.ss58_address,
- hotkey_ss58 = delegate_ss58,
- block=block
- ) # Get current stake
-
- bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( my_prev_coldkey_balance, new_balance ))
- bittensor.__console__.print("Stake:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( my_prev_delegated_stake, new_delegate_stake ))
- return True
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
- return False
-
- except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(wallet.hotkey_str))
- return False
- except StakeError as e:
- bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
- return False
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/prometheus.py b/commune/modules/bittensor/subtensor/extrinsics/prometheus.py
deleted file mode 100644
index 35050eda5..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/prometheus.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-import bittensor
-
-import json
-from rich.prompt import Confirm
-import bittensor.utils.networking as net
-from ..errors import *
-
-def prometheus_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- port: int,
- netuid: int,
- ip: int = None,
- wait_for_inclusion: bool = False,
- wait_for_finalization = True,
-) -> bool:
- r""" Subscribes an bittensor endpoint to the substensor chain.
- Args:
- subtensor (bittensor.subtensor):
- bittensor subtensor object.
- wallet (bittensor.wallet):
- bittensor wallet object.
- ip (str):
- endpoint host port i.e. 192.122.31.4
- port (int):
- endpoint port number i.e. 9221
- netuid (int):
- network uid to serve on.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
-
- # ---- Get external ip ----
- if ip == None:
- try:
- external_ip = net.get_external_ip()
- bittensor.__console__.print(":white_heavy_check_mark: [green]Found external ip: {}[/green]".format( external_ip ))
- bittensor.logging.success(prefix = 'External IP', sufix = '{}'.format( external_ip ))
- except Exception as E:
- raise RuntimeError('Unable to attain your external ip. Check your internet connection. error: {}'.format(E)) from E
- else:
- external_ip = ip
-
- call_params={
- 'version': bittensor.__version_as_int__,
- 'ip': net.ip_to_int(external_ip),
- 'port': port,
- 'ip_type': net.ip_version(external_ip),
- }
-
- with bittensor.__console__.status(":satellite: Checking Prometheus..."):
- neuron = subtensor.get_neuron_for_pubkey_and_subnet( wallet.hotkey.ss58_address, netuid = netuid )
- neuron_up_to_date = not neuron.is_null and call_params == {
- 'version': neuron.prometheus_info.version,
- 'ip': net.ip_to_int(neuron.prometheus_info.ip),
- 'port': neuron.prometheus_info.port,
- 'ip_type': neuron.prometheus_info.ip_type,
- }
-
- if neuron_up_to_date:
- bittensor.__console__.print(
- f":white_heavy_check_mark: [green]Prometheus already Served[/green]\n"
- f"[green not bold]- Status: [/green not bold] |"
- f"[green not bold] ip: [/green not bold][white not bold]{net.int_to_ip(neuron.prometheus_info.ip)}[/white not bold] |"
- f"[green not bold] ip_type: [/green not bold][white not bold]{neuron.prometheus_info.ip_type}[/white not bold] |"
- f"[green not bold] port: [/green not bold][white not bold]{neuron.prometheus_info.port}[/white not bold] | "
- f"[green not bold] version: [/green not bold][white not bold]{neuron.prometheus_info.version}[/white not bold] |"
- )
-
-
- bittensor.__console__.print(":white_heavy_check_mark: [white]Prometheus already served.[/white]".format( external_ip ))
- return True
-
- # Add netuid, not in prometheus_info
- call_params['netuid'] = netuid
-
- with bittensor.__console__.status(":satellite: Serving prometheus on: [white]{}:{}[/white] ...".format(subtensor.network, netuid)):
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='serve_prometheus',
- call_params = call_params
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey)
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- if wait_for_inclusion or wait_for_finalization:
- response.process_events()
- if response.is_success:
- bittensor.__console__.print(':white_heavy_check_mark: [green]Served prometheus[/green]\n [bold white]{}[/bold white]'.format(
- json.dumps(call_params, indent=4, sort_keys=True)
- ))
- return True
- else:
- bittensor.__console__.print(':cross_mark: [green]Failed to serve prometheus[/green] error: {}'.format(response.error_message))
- return False
- else:
- return True
-
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/registration.py b/commune/modules/bittensor/subtensor/extrinsics/registration.py
deleted file mode 100644
index b3bd08ef4..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/registration.py
+++ /dev/null
@@ -1,278 +0,0 @@
-
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-
-import torch
-import time
-from rich.prompt import Confirm
-from typing import List, Dict, Union, Optional
-import bittensor.utils.networking as net
-from ..errors import *
-import commune
-from commune.bittensor.utils import create_pow
-
-def register_extrinsic (
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.Wallet',
- netuid: int,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False,
- max_allowed_attempts: int = 3,
- output_in_place: bool = True,
- cuda: bool = False,
- dev_id: Union[List[int], int] = 0,
- TPB: int = 256,
- num_processes: Optional[int] = None,
- update_interval: Optional[int] = None,
- log_verbose: bool = False,
-) -> bool:
- r""" Registers the wallet to chain.
- Args:
- wallet (bittensor.wallet):
- bittensor wallet object.
- netuid (int):
- The netuid of the subnet to register on.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- max_allowed_attempts (int):
- Maximum number of attempts to register the wallet.
- cuda (bool):
- If true, the wallet should be registered using CUDA device(s).
- dev_id (Union[List[int], int]):
- The CUDA device id to use, or a list of device ids.
- TPB (int):
- The number of threads per block (CUDA).
- num_processes (int):
- The number of processes to use to register.
- update_interval (int):
- The number of nonces to solve between updates.
- log_verbose (bool):
- If true, the registration process will log more information.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if not subtensor.subnet_exists( netuid ):
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error: [bold white]subnet:{}[/bold white] does not exist.".format(netuid))
- return False
-
- with bittensor.__console__.status(f":satellite: Checking Account on [bold]subnet:{netuid}[/bold]..."):
- neuron = subtensor.get_neuron_for_pubkey_and_subnet( wallet.hotkey.ss58_address, netuid = netuid )
- if not neuron.is_null:
- bittensor.__console__.print(
- ':white_heavy_check_mark: [green]Already Registered[/green]:\n'\
- 'uid: [bold white]{}[/bold white]\n' \
- 'netuid: [bold white]{}[/bold white]\n' \
- 'hotkey: [bold white]{}[/bold white]\n' \
- 'coldkey: [bold white]{}[/bold white]'
- .format(neuron.uid, neuron.netuid, neuron.hotkey, neuron.coldkey))
- return True
-
- if prompt:
- if not Confirm.ask("Continue Registration?\n hotkey: [bold white]{}[/bold white]\n coldkey: [bold white]{}[/bold white]\n network: [bold white]{}[/bold white]".format( wallet.hotkey.ss58_address, wallet.coldkeypub.ss58_address, subtensor.network ) ):
- return False
-
- # Attempt rolling registration.
- attempts = 1
- while True:
- bittensor.__console__.print(":satellite: Registering...({}/{})".format(attempts, max_allowed_attempts))
- # Solve latest POW.
- if cuda:
- if not torch.cuda.is_available():
- if prompt:
- bittensor.__console__.error('CUDA is not available.')
- return False
-
- pow_result =create_pow( subtensor, wallet, netuid, output_in_place, cuda, dev_id, TPB, num_processes=num_processes, update_interval=update_interval, log_verbose=log_verbose )
- else:
- pow_result = create_pow( subtensor, wallet, netuid, output_in_place, num_processes=num_processes, update_interval=update_interval, log_verbose=log_verbose )
-
- # pow failed
- if not pow_result:
- # might be registered already on this subnet
- if (wallet.is_registered( subtensor = subtensor, netuid = netuid )):
- bittensor.__console__.print(f":white_heavy_check_mark: [green]Already registered on netuid:{netuid}[/green]")
- return True
-
- # pow successful, proceed to submit pow to chain for registration
- else:
- with bittensor.__console__.status(":satellite: Submitting POW..."):
- # check if pow result is still valid
- while bittensor.utils.POWNotStale(subtensor, pow_result):
- with subtensor.substrate as substrate:
- # create extrinsic call
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='register',
- call_params={
- 'netuid': netuid,
- 'block_number': pow_result['block_number'],
- 'nonce': pow_result['nonce'],
- 'work': bittensor.utils.hex_bytes_to_u8_list( pow_result['work'] ),
- 'hotkey': wallet.hotkey.ss58_address,
- 'coldkey': wallet.coldkeypub.ss58_address,
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization )
-
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- # process if registration successful, try again if pow is still valid
- response.process_events()
- if not response.is_success:
- if 'key is already registered' in response.error_message:
- # Error meant that the key is already registered.
- bittensor.__console__.print(f":white_heavy_check_mark: [green]Already Registered on [bold]subnet:{netuid}[/bold][/green]")
- return True
-
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
- time.sleep(0.5)
-
- # Successful registration, final check for neuron and pubkey
- else:
- bittensor.__console__.print(":satellite: Checking Balance...")
- is_registered = wallet.is_registered( subtensor = subtensor, netuid = netuid )
- if is_registered:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Registered[/green]")
- return True
- else:
- # neuron not found, try again
- bittensor.__console__.print(":cross_mark: [red]Unknown error. Neuron not found.[/red]")
- continue
- else:
- # Exited loop because pow is no longer valid.
- bittensor.__console__.print( "[red]POW is stale.[/red]" )
- # Try again.
- continue
-
- if attempts < max_allowed_attempts:
- #Failed registration, retry pow
- attempts += 1
- bittensor.__console__.print( ":satellite: Failed registration, retrying pow ...({}/{})".format(attempts, max_allowed_attempts))
- else:
- # Failed to register after max attempts.
- bittensor.__console__.print( "[red]No more attempts.[/red]" )
- return False
-
-
-def burned_register_extrinsic (
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.Wallet',
- netuid: int,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False
-) -> bool:
- r""" Registers the wallet to chain by recycling TAO.
- Args:
- wallet (bittensor.wallet):
- bittensor wallet object.
- netuid (int):
- The netuid of the subnet to register on.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if not subtensor.subnet_exists( netuid ):
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error: [bold white]subnet:{}[/bold white] does not exist.".format(netuid))
- return False
-
- wallet.coldkey # unlock coldkey
- with bittensor.__console__.status(f":satellite: Checking Account on [bold]subnet:{netuid}[/bold]..."):
- neuron = subtensor.get_neuron_for_pubkey_and_subnet( wallet.hotkey.ss58_address, netuid = netuid )
-
- old_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
-
- burn_amount = subtensor.burn( netuid = netuid )
- if not neuron.is_null:
- bittensor.__console__.print(
- ':white_heavy_check_mark: [green]Already Registered[/green]:\n'\
- 'uid: [bold white]{}[/bold white]\n' \
- 'netuid: [bold white]{}[/bold white]\n' \
- 'hotkey: [bold white]{}[/bold white]\n' \
- 'coldkey: [bold white]{}[/bold white]'
- .format(neuron.uid, neuron.netuid, neuron.hotkey, neuron.coldkey))
- return True
-
- if prompt:
- # Prompt user for confirmation.
- if not Confirm.ask( f"Recycle {burn_amount} to register on subnet:{netuid}?" ):
- return False
-
- with bittensor.__console__.status(":satellite: Recycling TAO for Registration..."):
- with subtensor.substrate as substrate:
- # create extrinsic call
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='burned_register',
- call_params={
- 'netuid': netuid,
- 'hotkey': wallet.hotkey.ss58_address
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization )
-
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- # process if registration successful, try again if pow is still valid
- response.process_events()
- if not response.is_success:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
- time.sleep(0.5)
-
- # Successful registration, final check for neuron and pubkey
- else:
- bittensor.__console__.print(":satellite: Checking Balance...")
- block = subtensor.get_current_block()
- new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address, block = block )
-
- bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
- is_registered = wallet.is_registered( subtensor = subtensor, netuid = netuid )
- if is_registered:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Registered[/green]")
- return True
- else:
- # neuron not found, try again
- bittensor.__console__.print(":cross_mark: [red]Unknown error. Neuron not found.[/red]")
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/serving.py b/commune/modules/bittensor/subtensor/extrinsics/serving.py
deleted file mode 100644
index 71ce06511..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/serving.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-import bittensor
-
-import json
-from rich.prompt import Confirm
-import bittensor.utils.networking as net
-from ..errors import *
-
-def serve_extrinsic (
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- ip: str,
- port: int,
- protocol: int,
- netuid: int,
- placeholder1: int = 0,
- placeholder2: int = 0,
- wait_for_inclusion: bool = False,
- wait_for_finalization = True,
- prompt: bool = False,
-) -> bool:
- r""" Subscribes an bittensor endpoint to the substensor chain.
- Args:
- wallet (bittensor.wallet):
- bittensor wallet object.
- ip (str):
- endpoint host port i.e. 192.122.31.4
- port (int):
- endpoint port number i.e. 9221
- protocol (int):
- int representation of the protocol
- netuid (int):
- network uid to serve on.
- placeholder1 (int):
- placeholder for future use.
- placeholder2 (int):
- placeholder for future use.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- # Decrypt hotkey
- wallet.hotkey
-
- params = {
- 'version': bittensor.__version_as_int__,
- 'ip': net.ip_to_int(ip),
- 'port': port,
- 'ip_type': net.ip_version(ip),
- 'netuid': netuid,
- 'coldkey': wallet.coldkeypub.ss58_address,
- 'protocol': protocol,
- 'placeholder1': placeholder1,
- 'placeholder2': placeholder2,
- }
-
- with bittensor.__console__.status(":satellite: Checking Axon..."):
- neuron = subtensor.get_neuron_for_pubkey_and_subnet( wallet.hotkey.ss58_address, netuid = netuid )
- neuron_up_to_date = not neuron.is_null and params == {
- 'version': neuron.axon_info.version,
- 'ip': net.ip_to_int(neuron.axon_info.ip),
- 'port': neuron.axon_info.port,
- 'ip_type': neuron.axon_info.ip_type,
- 'netuid': neuron.netuid,
- 'coldkey': neuron.coldkey,
- 'protocol': neuron.axon_info.protocol,
- 'placeholder1': neuron.axon_info.placeholder1,
- 'placeholder2': neuron.axon_info.placeholder2,
- }
-
- output = params.copy()
- output['coldkey'] = wallet.coldkeypub.ss58_address
- output['hotkey'] = wallet.hotkey.ss58_address
-
- if neuron_up_to_date:
- bittensor.__console__.print(f":white_heavy_check_mark: [green]Axon already Served[/green]\n"
- f"[green not bold]- coldkey: [/green not bold][white not bold]{output['coldkey']}[/white not bold] \n"
- f"[green not bold]- hotkey: [/green not bold][white not bold]{output['hotkey']}[/white not bold] \n"
- f"[green not bold]- Status: [/green not bold] |"
- f"[green not bold] ip: [/green not bold][white not bold]{net.int_to_ip(output['ip'])}[/white not bold] |"
- f"[green not bold] ip_type: [/green not bold][white not bold]{output['ip_type']}[/white not bold] |"
- f"[green not bold] port: [/green not bold][white not bold]{output['port']}[/white not bold] | "
- f"[green not bold] netuid: [/green not bold][white not bold]{output['netuid']}[/white not bold] |"
- f"[green not bold] protocol: [/green not bold][white not bold]{output['protocol']}[/white not bold] |"
- f"[green not bold] version: [/green not bold][white not bold]{output['version']}[/white not bold] |"
- )
-
-
- return True
-
- if prompt:
- output = params.copy()
- output['coldkey'] = wallet.coldkeypub.ss58_address
- output['hotkey'] = wallet.hotkey.ss58_address
- if not Confirm.ask("Do you want to serve axon:\n [bold white]{}[/bold white]".format(
- json.dumps(output, indent=4, sort_keys=True)
- )):
- return False
-
- with bittensor.__console__.status(":satellite: Serving axon on: [white]{}:{}[/white] ...".format(subtensor.network, netuid)):
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='serve_axon',
- call_params=params
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey)
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- if wait_for_inclusion or wait_for_finalization:
- response.process_events()
- if response.is_success:
- bittensor.__console__.print(':white_heavy_check_mark: [green]Served[/green]\n [bold white]{}[/bold white]'.format(
- json.dumps(params, indent=4, sort_keys=True)
- ))
- return True
- else:
- bittensor.__console__.print(':cross_mark: [green]Failed to Serve axon[/green] error: {}'.format(response.error_message))
- return False
- else:
- return True
-
-def serve_axon_extrinsic (
- subtensor: 'bittensor.Subtensor',
- axon: 'bittensor.Axon',
- use_upnpc: bool = False,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False,
-) -> bool:
- r""" Serves the axon to the network.
- Args:
- axon (bittensor.Axon):
- Axon to serve.
- use_upnpc (:type:bool, `optional`):
- If true, the axon attempts port forward through your router before
- subscribing.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- axon.wallet.hotkey
- axon.wallet.coldkeypub
-
- # ---- Setup UPNPC ----
- if use_upnpc:
- if prompt:
- if not Confirm.ask("Attempt port forwarding with upnpc?"):
- return False
- try:
- external_port = net.upnpc_create_port_map( port = axon.port )
- bittensor.__console__.print(":white_heavy_check_mark: [green]Forwarded port: {}[/green]".format( axon.port ))
- bittensor.logging.success(prefix = 'Forwarded port', sufix = '{}'.format( axon.port ))
- except net.UPNPCException as upnpc_exception:
- raise RuntimeError('Failed to hole-punch with upnpc with exception {}'.format( upnpc_exception )) from upnpc_exception
- else:
- external_port = axon.external_port
-
- # ---- Get external ip ----
- if axon.external_ip == None:
- try:
- external_ip = net.get_external_ip()
- bittensor.__console__.print(":white_heavy_check_mark: [green]Found external ip: {}[/green]".format( external_ip ))
- bittensor.logging.success(prefix = 'External IP', sufix = '{}'.format( external_ip ))
- except Exception as E:
- raise RuntimeError('Unable to attain your external ip. Check your internet connection. error: {}'.format(E)) from E
- else:
- external_ip = axon.external_ip
-
- # ---- Subscribe to chain ----
- serve_success = subtensor.serve(
- wallet = axon.wallet,
- ip = external_ip,
- port = external_port,
- netuid = axon.netuid,
- protocol = axon.protocol,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
- return serve_success
diff --git a/commune/modules/bittensor/subtensor/extrinsics/set_weights.py b/commune/modules/bittensor/subtensor/extrinsics/set_weights.py
deleted file mode 100644
index 06164337f..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/set_weights.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-
-import torch
-from rich.prompt import Confirm
-from typing import Union
-import bittensor.utils.weight_utils as weight_utils
-from ..errors import *
-
-from loguru import logger
-logger = logger.opt(colors=True)
-
-def set_weights_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- netuid: int,
- uids: Union[torch.LongTensor, list],
- weights: Union[torch.FloatTensor, list],
- version_key: int = 0,
- wait_for_inclusion:bool = False,
- wait_for_finalization:bool = False,
- prompt:bool = False
- ) -> bool:
- r""" Sets the given weights and values on chain for wallet hotkey account.
- Args:
- wallet (bittensor.wallet):
- bittensor wallet object.
- netuid (int):
- netuid of the subent to set weights for.
- uids (Union[torch.LongTensor, list]):
- uint64 uids of destination neurons.
- weights ( Union[torch.FloatTensor, list]):
- weights to set which must floats and correspond to the passed uids.
- version_key (int):
- version key of the validator.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- # First convert types.
- if isinstance( uids, list ):
- uids = torch.tensor( uids, dtype = torch.int64 )
- if isinstance( weights, list ):
- weights = torch.tensor( weights, dtype = torch.float32 )
-
- # Reformat and normalize.
- weight_uids, weight_vals = weight_utils.convert_weights_and_uids_for_emit( uids, weights )
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to set weights:\n[bold white] weights: {}\n uids: {}[/bold white ]?".format( [float(v/65535) for v in weight_vals], weight_uids) ):
- return False
-
- with bittensor.__console__.status(":satellite: Setting weights on [white]{}[/white] ...".format(subtensor.network)):
- try:
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='set_weights',
- call_params = {
- 'dests': weight_uids,
- 'weights': weight_vals,
- 'netuid': netuid,
- 'version_key': version_key,
- }
- )
- # Period dictates how long the extrinsic will stay as part of waiting pool
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey, era={'period':100})
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- response.process_events()
- if response.is_success:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- bittensor.logging.success( prefix = 'Set weights', sufix = 'Finalized: ' + str(response.is_success) )
- return True
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
- bittensor.logging.warning( prefix = 'Set weights', sufix = 'Failed: ' + str(response.error_message) )
- return False
-
- except Exception as e:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(e))
- bittensor.logging.warning( prefix = 'Set weights', sufix = 'Failed: ' + str(e) )
- return False
-
- if response.is_success:
- bittensor.__console__.print("Set weights:\n[bold white] weights: {}\n uids: {}[/bold white ]".format( [float(v/4294967295) for v in weight_vals], weight_uids ))
- message = 'Success: ' + f'Set {len(uids)} weights, top 5 weights' + str(list(zip(uids.tolist()[:5], [round (w,4) for w in weights.tolist()[:5]] )))
- logger.debug('Set weights:'.ljust(20) + message)
- return True
-
- return False
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/staking.py b/commune/modules/bittensor/subtensor/extrinsics/staking.py
deleted file mode 100644
index 214101a30..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/staking.py
+++ /dev/null
@@ -1,388 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-
-from rich.prompt import Confirm
-from typing import List, Dict, Union, Optional
-from bittensor.utils.balance import Balance
-from ..errors import *
-
-def add_stake_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- hotkey_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- r""" Adds the specified amount of stake to passed hotkey uid.
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object.
- hotkey_ss58 (Optional[str]):
- ss58 address of the hotkey account to stake to
- defaults to the wallet's hotkey.
- amount (Union[Balance, float]):
- Amount to stake as bittensor balance, or float interpreted as Tao.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
-
- Raises:
- NotRegisteredError:
- If the wallet is not registered on the chain.
- NotDelegateError:
- If the hotkey is not a delegate on the chain.
- """
- # Decrypt keys,
- wallet.coldkey
-
- # Default to wallet's own hotkey if the value is not passed.
- if hotkey_ss58 is None:
- hotkey_ss58 = wallet.hotkey.ss58_address
-
- # Flag to indicate if we are using the wallet's own hotkey.
- own_hotkey: bool = (wallet.hotkey.ss58_address == hotkey_ss58)
-
- with bittensor.__console__.status(":satellite: Syncing with chain: [white]{}[/white] ...".format(subtensor.network)):
- old_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
- # Get hotkey owner
- hotkey_owner = subtensor.get_hotkey_owner( hotkey_ss58 )
- own_hotkey = (wallet.coldkeypub.ss58_address == hotkey_owner)
- if not own_hotkey:
- # This is not the wallet's own hotkey so we are delegating.
- if not subtensor.is_hotkey_delegate( hotkey_ss58 ):
- raise NotDelegateError("Hotkey: {} is not a delegate.".format(hotkey_ss58))
-
- # Get hotkey take
- hotkey_take = subtensor.get_delegate_take( hotkey_ss58 )
-
- # Get current stake
- old_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58=wallet.coldkeypub.ss58_address, hotkey_ss58=hotkey_ss58 )
-
- # Convert to bittensor.Balance
- if amount == None:
- # Stake it all.
- staking_balance = bittensor.Balance.from_tao( old_balance.tao )
- elif not isinstance(amount, bittensor.Balance ):
- staking_balance = bittensor.Balance.from_tao( amount )
- else:
- staking_balance = amount
-
- # Remove existential balance to keep key alive.
- if staking_balance > bittensor.Balance.from_rao( 1000 ):
- staking_balance = staking_balance - bittensor.Balance.from_rao( 1000 )
- else:
- staking_balance = staking_balance
-
- # Check enough to stake.
- if staking_balance > old_balance:
- bittensor.__console__.print(":cross_mark: [red]Not enough stake[/red]:[bold white]\n balance:{}\n amount: {}\n coldkey: {}[/bold white]".format(old_balance, staking_balance, wallet.name))
- return False
-
- # Ask before moving on.
- if prompt:
- if not own_hotkey:
- # We are delegating.
- if not Confirm.ask("Do you want to delegate:[bold white]\n amount: {}\n to: {}\n take: {}\n owner: {}[/bold white]".format( staking_balance, wallet.hotkey_str, hotkey_take, hotkey_owner) ):
- return False
- else:
- if not Confirm.ask("Do you want to stake:[bold white]\n amount: {}\n to: {}[/bold white]".format( staking_balance, wallet.hotkey_str) ):
- return False
-
- try:
- with bittensor.__console__.status(":satellite: Staking to: [bold white]{}[/bold white] ...".format(subtensor.network)):
- staking_response: bool = __do_add_stake_single(
- subtensor = subtensor,
- wallet = wallet,
- hotkey_ss58 = hotkey_ss58,
- amount = staking_balance,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- )
-
- if staking_response: # If we successfully staked.
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- with bittensor.__console__.status(":satellite: Checking Balance on: [white]{}[/white] ...".format(subtensor.network)):
- new_balance = subtensor.get_balance( address = wallet.coldkeypub.ss58_address )
- block = subtensor.get_current_block()
- new_stake = subtensor.get_stake_for_coldkey_and_hotkey(
- coldkey_ss58=wallet.coldkeypub.ss58_address,
- hotkey_ss58= wallet.hotkey.ss58_address,
- block=block
- ) # Get current stake
-
- bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
- bittensor.__console__.print("Stake:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_stake, new_stake ))
- return True
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
- return False
-
- except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(wallet.hotkey_str))
- return False
- except StakeError as e:
- bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
- return False
-
-
-def add_stake_multiple_extrinsic (
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- hotkey_ss58s: List[str],
- amounts: List[Union[Balance, float]] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- r""" Adds stake to each hotkey_ss58 in the list, using each amount, from a common coldkey.
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object for the coldkey.
- hotkey_ss58s (List[str]):
- List of hotkeys to stake to.
- amounts (List[Union[Balance, float]]):
- List of amounts to stake. If None, stake all to the first hotkey.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or included in the block.
- flag is true if any wallet was staked.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if not isinstance(hotkey_ss58s, list) or not all(isinstance(hotkey_ss58, str) for hotkey_ss58 in hotkey_ss58s):
- raise TypeError("hotkey_ss58s must be a list of str")
-
- if len(hotkey_ss58s) == 0:
- return True
-
- if amounts is not None and len(amounts) != len(hotkey_ss58s):
- raise ValueError("amounts must be a list of the same length as hotkey_ss58s")
-
- if amounts is not None and not all(isinstance(amount, (Balance, float)) for amount in amounts):
- raise TypeError("amounts must be a [list of bittensor.Balance or float] or None")
-
- if amounts is None:
- amounts = [None] * len(hotkey_ss58s)
- else:
- # Convert to Balance
- amounts = [bittensor.Balance.from_tao(amount) if isinstance(amount, float) else amount for amount in amounts ]
-
- if sum(amount.tao for amount in amounts) == 0:
- # Staking 0 tao
- return True
-
- # Decrypt coldkey.
- wallet.coldkey
-
- old_stakes = []
- with bittensor.__console__.status(":satellite: Syncing with chain: [white]{}[/white] ...".format(subtensor.network)):
- old_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
-
- # Get the old stakes.
- for hotkey_ss58 in hotkey_ss58s:
- old_stakes.append( subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58 ) )
-
- # Remove existential balance to keep key alive.
- ## Keys must maintain a balance of at least 1000 rao to stay alive.
- total_staking_rao = sum([amount.rao if amount is not None else 0 for amount in amounts])
- if total_staking_rao == 0:
- # Staking all to the first wallet.
- if old_balance.rao > 1000:
- old_balance -= bittensor.Balance.from_rao(1000)
-
- elif total_staking_rao < 1000:
- # Staking less than 1000 rao to the wallets.
- pass
- else:
- # Staking more than 1000 rao to the wallets.
- ## Reduce the amount to stake to each wallet to keep the balance above 1000 rao.
- percent_reduction = 1 - (1000 / total_staking_rao)
- amounts = [Balance.from_tao(amount.tao * percent_reduction) for amount in amounts]
-
- successful_stakes = 0
- for hotkey_ss58, amount, old_stake in zip(hotkey_ss58s, amounts, old_stakes):
- staking_all = False
- # Convert to bittensor.Balance
- if amount == None:
- # Stake it all.
- staking_balance = bittensor.Balance.from_tao( old_balance.tao )
- staking_all = True
- else:
- # Amounts are cast to balance earlier in the function
- assert isinstance(amount, bittensor.Balance)
- staking_balance = amount
-
- # Check enough to stake
- if staking_balance > old_balance:
- bittensor.__console__.print(":cross_mark: [red]Not enough balance[/red]: [green]{}[/green] to stake: [blue]{}[/blue] from coldkey: [white]{}[/white]".format(old_balance, staking_balance, wallet.name))
- continue
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to stake:\n[bold white] amount: {}\n hotkey: {}[/bold white ]?".format( staking_balance, wallet.hotkey_str) ):
- continue
-
- try:
- staking_response: bool = __do_add_stake_single(
- subtensor = subtensor,
- wallet = wallet,
- hotkey_ss58 = hotkey_ss58,
- amount = staking_balance,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- )
-
- if staking_response: # If we successfully staked.
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- old_balance -= staking_balance
- successful_stakes += 1
- if staking_all:
- # If staked all, no need to continue
- break
-
- continue
-
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
-
- block = subtensor.get_current_block()
- new_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58, block = block )
- new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address, block = block )
- bittensor.__console__.print("Stake ({}): [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( hotkey_ss58, old_stake, new_stake ))
- old_balance = new_balance
- successful_stakes += 1
- if staking_all:
- # If staked all, no need to continue
- break
-
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
- continue
-
- except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(hotkey_ss58))
- continue
- except StakeError as e:
- bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
- continue
-
-
- if successful_stakes != 0:
- with bittensor.__console__.status(":satellite: Checking Balance on: ([white]{}[/white] ...".format(subtensor.network)):
- new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
- bittensor.__console__.print("Balance: [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
- return True
-
- return False
-
-def __do_add_stake_single(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- hotkey_ss58: str,
- amount: 'bittensor.Balance',
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- ) -> bool:
- r"""
- Executes a stake call to the chain using the wallet and amount specified.
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object.
- hotkey_ss58 (str):
- Hotkey to stake to.
- amount (bittensor.Balance):
- Amount to stake as bittensor balance object.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- Raises:
- StakeError:
- If the extrinsic fails to be finalized or included in the block.
- NotDelegateError:
- If the hotkey is not a delegate.
- NotRegisteredError:
- If the hotkey is not registered in any subnets.
-
- """
- # Decrypt keys,
- wallet.coldkey
- wallet.hotkey
-
- hotkey_owner = subtensor.get_hotkey_owner( hotkey_ss58 )
- own_hotkey = (wallet.coldkeypub.ss58_address == hotkey_owner)
- if not own_hotkey:
- # We are delegating.
- # Verify that the hotkey is a delegate.
- if not subtensor.is_hotkey_delegate( hotkey_ss58 = hotkey_ss58 ):
- raise NotDelegateError("Hotkey: {} is not a delegate.".format(hotkey_ss58))
-
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='add_stake',
- call_params={
- 'hotkey': hotkey_ss58,
- 'amount_staked': amount.rao
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- return True
-
- response.process_events()
- if response.is_success:
- return True
- else:
- raise StakeError(response.error_message)
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/transfer.py b/commune/modules/bittensor/subtensor/extrinsics/transfer.py
deleted file mode 100644
index 8b5ed9c7a..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/transfer.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-
-from rich.prompt import Confirm
-from typing import List, Dict, Union
-from bittensor.utils.balance import Balance
-from bittensor.utils import is_valid_bittensor_address_or_public_key
-from ..errors import *
-
-def transfer_extrinsic(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- dest: str,
- amount: Union[Balance, float],
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- keep_alive: bool = True,
- prompt: bool = False,
- ) -> bool:
- r""" Transfers funds from this wallet to the destination public key address
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object to make transfer from.
- dest (str, ss58_address or ed25519):
- Destination public key address of reciever.
- amount (Union[Balance, int]):
- Amount to stake as bittensor balance, or float interpreted as Tao.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- keep_alive (bool):
- If set, keeps the account alive by keeping the balance above the existential deposit.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- Flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- # Validate destination address.
- if not is_valid_bittensor_address_or_public_key( dest ):
- bittensor.__console__.print(":cross_mark: [red]Invalid destination address[/red]:[bold white]\n {}[/bold white]".format(dest))
- return False
-
- if isinstance( dest, bytes):
- # Convert bytes to hex string.
- dest = "0x" + dest.hex()
-
- # Unlock wallet coldkey.
- wallet.coldkey
-
- # Convert to bittensor.Balance
- if not isinstance(amount, bittensor.Balance ):
- transfer_balance = bittensor.Balance.from_tao( amount )
- else:
- transfer_balance = amount
-
- # Check balance.
- with bittensor.__console__.status(":satellite: Checking Balance..."):
- account_balance = subtensor.get_balance( wallet.coldkey.ss58_address )
- # check existential deposit.
- existential_deposit = subtensor.get_existential_deposit()
-
- with bittensor.__console__.status(":satellite: Transferring..."):
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='Balances',
- call_function='transfer',
- call_params={
- 'dest': dest,
- 'value': transfer_balance.rao
- }
- )
-
- try:
- payment_info = substrate.get_payment_info( call = call, keypair = wallet.coldkey )
- except Exception as e:
- bittensor.__console__.print(":cross_mark: [red]Failed to get payment info[/red]:[bold white]\n {}[/bold white]".format(e))
- payment_info = {
- 'partialFee': 2e7, # assume 0.02 Tao
- }
-
- fee = bittensor.Balance.from_rao( payment_info['partialFee'] )
-
- if not keep_alive:
- # Check if the transfer should keep_alive the account
- existential_deposit = bittensor.Balance(0)
-
- # Check if we have enough balance.
- if account_balance < (transfer_balance + fee + existential_deposit):
- bittensor.__console__.print(":cross_mark: [red]Not enough balance[/red]:[bold white]\n balance: {}\n amount: {}\n for fee: {}[/bold white]".format( account_balance, transfer_balance, fee ))
- return False
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to transfer:[bold white]\n amount: {}\n from: {}:{}\n to: {}\n for fee: {}[/bold white]".format( transfer_balance, wallet.name, wallet.coldkey.ss58_address, dest, fee )):
- return False
-
- with bittensor.__console__.status(":satellite: Transferring..."):
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='Balances',
- call_function='transfer',
- call_params={
- 'dest': dest,
- 'value': transfer_balance.rao
- }
- )
-
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- # Otherwise continue with finalization.
- response.process_events()
- if response.is_success:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- block_hash = response.block_hash
- bittensor.__console__.print("[green]Block Hash: {}[/green]".format( block_hash ))
-
- explorer_url = bittensor.utils.get_explorer_url_for_network( subtensor.network, block_hash, bittensor.__network_explorer_map__ )
- if explorer_url is not None:
- bittensor.__console__.print("[green]Explorer Link: {}[/green]".format( explorer_url ))
-
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
-
- if response.is_success:
- with bittensor.__console__.status(":satellite: Checking Balance..."):
- new_balance = subtensor.get_balance( wallet.coldkey.ss58_address )
- bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format(account_balance, new_balance))
- return True
-
- return False
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/extrinsics/unstaking.py b/commune/modules/bittensor/subtensor/extrinsics/unstaking.py
deleted file mode 100644
index 82e01151b..000000000
--- a/commune/modules/bittensor/subtensor/extrinsics/unstaking.py
+++ /dev/null
@@ -1,311 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import bittensor
-
-from rich.prompt import Confirm
-from typing import List, Dict, Union, Optional
-from bittensor.utils.balance import Balance
-from ..errors import *
-
-def __do_remove_stake_single(
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- hotkey_ss58: str,
- amount: 'bittensor.Balance',
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
-) -> bool:
- r"""
- Executes an unstake call to the chain using the wallet and amount specified.
- Args:
- wallet (bittensor.wallet):
- Bittensor wallet object.
- hotkey_ss58 (str):
- Hotkey address to unstake from.
- amount (bittensor.Balance):
- Amount to unstake as bittensor balance object.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- Raises:
- StakeError:
- If the extrinsic fails to be finalized or included in the block.
- NotRegisteredError:
- If the hotkey is not registered in any subnets.
-
- """
- # Decrypt keys,
- wallet.coldkey
-
- with subtensor.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='remove_stake',
- call_params={
- 'hotkey': hotkey_ss58,
- 'amount_unstaked': amount.rao
- }
- )
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- return True
-
- response.process_events()
- if response.is_success:
- return True
- else:
- raise StakeError(response.error_message)
-
-def unstake_extrinsic (
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- hotkey_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion:bool = True,
- wait_for_finalization:bool = False,
- prompt: bool = False,
- ) -> bool:
- r""" Removes stake into the wallet coldkey from the specified hotkey uid.
- Args:
- wallet (bittensor.wallet):
- bittensor wallet object.
- hotkey_ss58 (Optional[str]):
- ss58 address of the hotkey to unstake from.
- by default, the wallet hotkey is used.
- amount (Union[Balance, float]):
- Amount to stake as bittensor balance, or float interpreted as tao.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- # Decrypt keys,
- wallet.coldkey
-
- if hotkey_ss58 is None:
- hotkey_ss58 = wallet.hotkey.ss58_address # Default to wallet's own hotkey.
-
- with bittensor.__console__.status(":satellite: Syncing with chain: [white]{}[/white] ...".format(subtensor.network)):
- old_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
- old_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58 )
-
- # Convert to bittensor.Balance
- if amount == None:
- # Unstake it all.
- unstaking_balance = old_stake
- elif not isinstance(amount, bittensor.Balance ):
- unstaking_balance = bittensor.Balance.from_tao( amount )
- else:
- unstaking_balance = amount
-
- # Check enough to unstake.
- stake_on_uid = old_stake
- if unstaking_balance > stake_on_uid:
- bittensor.__console__.print(":cross_mark: [red]Not enough stake[/red]: [green]{}[/green] to unstake: [blue]{}[/blue] from hotkey: [white]{}[/white]".format(stake_on_uid, unstaking_balance, wallet.hotkey_str))
- return False
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to unstake:\n[bold white] amount: {}\n hotkey: {}[/bold white ]?".format( unstaking_balance, wallet.hotkey_str) ):
- return False
-
-
- try:
- with bittensor.__console__.status(":satellite: Unstaking from chain: [white]{}[/white] ...".format(subtensor.network)):
- staking_response: bool = __do_remove_stake_single(
- subtensor = subtensor,
- wallet = wallet,
- hotkey_ss58 = hotkey_ss58,
- amount = unstaking_balance,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- )
-
- if staking_response: # If we successfully unstaked.
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- return True
-
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- with bittensor.__console__.status(":satellite: Checking Balance on: [white]{}[/white] ...".format(subtensor.network)):
- new_balance = subtensor.get_balance( address = wallet.coldkeypub.ss58_address )
- new_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58 ) # Get stake on hotkey.
- bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
- bittensor.__console__.print("Stake:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_stake, new_stake ))
- return True
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
- return False
-
- except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(wallet.hotkey_str))
- return False
- except StakeError as e:
- bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
- return False
-
-def unstake_multiple_extrinsic (
- subtensor: 'bittensor.Subtensor',
- wallet: 'bittensor.wallet',
- hotkey_ss58s: List[str],
- amounts: List[Union[Balance, float]] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- r""" Removes stake from each hotkey_ss58 in the list, using each amount, to a common coldkey.
- Args:
- wallet (bittensor.wallet):
- The wallet with the coldkey to unstake to.
- hotkey_ss58s (List[str]):
- List of hotkeys to unstake from.
- amounts (List[Union[Balance, float]]):
- List of amounts to unstake. If None, unstake all.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or included in the block.
- flag is true if any wallet was unstaked.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if not isinstance(hotkey_ss58s, list) or not all(isinstance(hotkey_ss58, str) for hotkey_ss58 in hotkey_ss58s):
- raise TypeError("hotkey_ss58s must be a list of str")
-
- if len(hotkey_ss58s) == 0:
- return True
-
- if amounts is not None and len(amounts) != len(hotkey_ss58s):
- raise ValueError("amounts must be a list of the same length as hotkey_ss58s")
-
- if amounts is not None and not all(isinstance(amount, (Balance, float)) for amount in amounts):
- raise TypeError("amounts must be a [list of bittensor.Balance or float] or None")
-
- if amounts is None:
- amounts = [None] * len(hotkey_ss58s)
- else:
- # Convert to Balance
- amounts = [bittensor.Balance.from_tao(amount) if isinstance(amount, float) else amount for amount in amounts ]
-
- if sum(amount.tao for amount in amounts) == 0:
- # Staking 0 tao
- return True
-
- # Unlock coldkey.
- wallet.coldkey
-
- old_stakes = []
- with bittensor.__console__.status(":satellite: Syncing with chain: [white]{}[/white] ...".format(subtensor.network)):
- old_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
-
- for hotkey_ss58 in hotkey_ss58s:
- old_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58 ) # Get stake on hotkey.
- old_stakes.append(old_stake) # None if not registered.
-
- successful_unstakes = 0
- for hotkey_ss58, amount, old_stake in zip(hotkey_ss58s, amounts, old_stakes):
- # Covert to bittensor.Balance
- if amount == None:
- # Unstake it all.
- unstaking_balance = old_stake
- elif not isinstance(amount, bittensor.Balance ):
- unstaking_balance = bittensor.Balance.from_tao( amount )
- else:
- unstaking_balance = amount
-
- # Check enough to unstake.
- stake_on_uid = old_stake
- if unstaking_balance > stake_on_uid:
- bittensor.__console__.print(":cross_mark: [red]Not enough stake[/red]: [green]{}[/green] to unstake: [blue]{}[/blue] from hotkey: [white]{}[/white]".format(stake_on_uid, unstaking_balance, wallet.hotkey_str))
- continue
-
- # Ask before moving on.
- if prompt:
- if not Confirm.ask("Do you want to unstake:\n[bold white] amount: {}\n hotkey: {}[/bold white ]?".format( unstaking_balance, wallet.hotkey_str) ):
- continue
-
- try:
- with bittensor.__console__.status(":satellite: Unstaking from chain: [white]{}[/white] ...".format(subtensor.network)):
- staking_response: bool = __do_remove_stake_single(
- subtensor = subtensor,
- wallet = wallet,
- hotkey_ss58 = hotkey_ss58,
- amount = unstaking_balance,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- )
-
- if staking_response: # If we successfully unstaked.
- # We only wait here if we expect finalization.
- if not wait_for_finalization and not wait_for_inclusion:
- bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
- successful_unstakes += 1
- continue
-
- bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
- with bittensor.__console__.status(":satellite: Checking Balance on: [white]{}[/white] ...".format(subtensor.network)):
- block = subtensor.get_current_block()
- new_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58, block = block )
- bittensor.__console__.print("Stake ({}): [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( hotkey_ss58, stake_on_uid, new_stake ))
- successful_unstakes += 1
- else:
- bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
- continue
-
- except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]{} is not registered.[/red]".format(hotkey_ss58))
- continue
- except StakeError as e:
- bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
- continue
-
-
- if successful_unstakes != 0:
- with bittensor.__console__.status(":satellite: Checking Balance on: ([white]{}[/white] ...".format(subtensor.network)):
- new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
- bittensor.__console__.print("Balance: [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
- return True
-
- return False
\ No newline at end of file
diff --git a/commune/modules/bittensor/subtensor/subtensor_impl.py b/commune/modules/bittensor/subtensor/subtensor_impl.py
deleted file mode 100644
index 65d943273..000000000
--- a/commune/modules/bittensor/subtensor/subtensor_impl.py
+++ /dev/null
@@ -1,1072 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-# Imports
-import torch
-import bittensor
-import scalecodec
-from retry import retry
-from typing import List, Dict, Union, Optional, Tuple
-from substrateinterface import SubstrateInterface
-from bittensor.utils.balance import Balance
-from bittensor.utils import U16_NORMALIZED_FLOAT, U64_MAX, RAOPERTAO, U16_MAX
-
-# Local imports.
-from .chain_data import NeuronInfo, AxonInfo, DelegateInfo, PrometheusInfo, SubnetInfo, NeuronInfoLite
-from .errors import *
-from .extrinsics.staking import add_stake_extrinsic, add_stake_multiple_extrinsic
-from .extrinsics.unstaking import unstake_extrinsic, unstake_multiple_extrinsic
-from .extrinsics.serving import serve_extrinsic, serve_axon_extrinsic
-from .extrinsics.registration import register_extrinsic, burned_register_extrinsic
-from .extrinsics.transfer import transfer_extrinsic
-from .extrinsics.set_weights import set_weights_extrinsic
-from .extrinsics.prometheus import prometheus_extrinsic
-from .extrinsics.delegation import delegate_extrinsic, nominate_extrinsic,undelegate_extrinsic
-
-# Logging
-from loguru import logger
-logger = logger.opt(colors=True)
-
-class Subtensor:
- """
- Handles interactions with the subtensor chain.
- """
- def __init__(
- self,
- substrate: 'SubstrateInterface',
- network: str,
- chain_endpoint: str,
- ):
- r""" Initializes a subtensor chain interface.
- Args:
- substrate (:obj:`SubstrateInterface`, `required`):
- substrate websocket client.
- network (default='local', type=str)
- The subtensor network flag. The likely choices are:
- -- local (local running network)
- -- nobunaga (staging network)
- -- nakamoto (main network)
- If this option is set it overloads subtensor.chain_endpoint with
- an entry point node from that network.
- chain_endpoint (default=None, type=str)
- The subtensor endpoint flag. If set, overrides the network argument.
- """
- self.network = network
- self.chain_endpoint = chain_endpoint
- self.substrate = substrate
-
- def __str__(self) -> str:
- if self.network == self.chain_endpoint:
- # Connecting to chain endpoint without network known.
- return "Subtensor({})".format( self.chain_endpoint )
- else:
- # Connecting to network with endpoint known.
- return "Subtensor({}, {})".format( self.network, self.chain_endpoint )
-
- def __repr__(self) -> str:
- return self.__str__()
-
- #####################
- #### Delegation #####
- #####################
- def nominate(
- self,
- wallet: 'bittensor.Wallet',
- wait_for_finalization: bool = False,
- wait_for_inclusion: bool = True
- ) -> bool:
- """ Becomes a delegate for the hotkey."""
- return nominate_extrinsic(
- subtensor = self,
- wallet = wallet,
- wait_for_finalization = wait_for_finalization,
- wait_for_inclusion = wait_for_inclusion
- )
-
- def delegate(
- self,
- wallet: 'bittensor.wallet',
- delegate_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Adds the specified amount of stake to the passed delegate using the passed wallet. """
- return delegate_extrinsic(
- subtensor = self,
- wallet = wallet,
- delegate_ss58 = delegate_ss58,
- amount = amount,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- def undelegate(
- self,
- wallet: 'bittensor.wallet',
- delegate_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Removes the specified amount of stake from the passed delegate using the passed wallet. """
- return undelegate_extrinsic(
- subtensor = self,
- wallet = wallet,
- delegate_ss58 = delegate_ss58,
- amount = amount,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- #####################
- #### Set Weights ####
- #####################
- def set_weights(
- self,
- wallet: 'bittensor.wallet',
- netuid: int,
- uids: Union[torch.LongTensor, list],
- weights: Union[torch.FloatTensor, list],
- version_key: int = bittensor.__version_as_int__,
- wait_for_inclusion:bool = False,
- wait_for_finalization:bool = False,
- prompt:bool = False
- ) -> bool:
- return set_weights_extrinsic(
- subtensor=self,
- wallet=wallet,
- netuid=netuid,
- uids=uids,
- weights=weights,
- version_key=version_key,
- wait_for_inclusion=wait_for_inclusion,
- wait_for_finalization=wait_for_finalization,
- prompt=prompt,
- )
-
- ######################
- #### Registration ####
- ######################
- def register (
- self,
- wallet: 'bittensor.Wallet',
- netuid: int,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False,
- max_allowed_attempts: int = 3,
- output_in_place: bool = True,
- cuda: bool = False,
- dev_id: Union[List[int], int] = 0,
- TPB: int = 256,
- num_processes: Optional[int] = None,
- update_interval: Optional[int] = None,
- log_verbose: bool = False,
- ) -> bool:
- """ Registers the wallet to chain."""
- return register_extrinsic(
- subtensor = self,
- wallet = wallet,
- netuid = netuid,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt,
- max_allowed_attempts = max_allowed_attempts,
- output_in_place = output_in_place,
- cuda = cuda,
- dev_id = dev_id,
- TPB = TPB,
- num_processes = num_processes,
- update_interval = update_interval,
- log_verbose = log_verbose,
- )
-
- def burned_register (
- self,
- wallet: 'bittensor.Wallet',
- netuid: int,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False
- ) -> bool:
- """ Registers the wallet to chain by recycling TAO."""
- return burned_register_extrinsic(
- subtensor = self,
- wallet = wallet,
- netuid = netuid,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- ##################
- #### Transfer ####
- ##################
- def transfer(
- self,
- wallet: 'bittensor.wallet',
- dest: str,
- amount: Union[Balance, float],
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Transfers funds from this wallet to the destination public key address"""
- return transfer_extrinsic(
- subtensor = self,
- wallet = wallet,
- dest = dest,
- amount = amount,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- def get_existential_deposit(
- self,
- block: Optional[int] = None,
- ) -> Optional[Balance]:
- """ Returns the existential deposit for the chain. """
- result = self.query_constant(
- module_name='Balances',
- constant_name='ExistentialDeposit',
- block = block,
- )
-
- if result is None:
- return None
-
- return Balance.from_rao(result.value)
-
- #################
- #### Serving ####
- #################
- def serve (
- self,
- wallet: 'bittensor.wallet',
- ip: str,
- port: int,
- protocol: int,
- netuid: int,
- placeholder1: int = 0,
- placeholder2: int = 0,
- wait_for_inclusion: bool = False,
- wait_for_finalization = True,
- prompt: bool = False,
- ) -> bool:
- return serve_extrinsic( self, wallet, ip, port, protocol, netuid , placeholder1, placeholder2, wait_for_inclusion, wait_for_finalization)
-
- def serve_axon (
- self,
- axon: 'bittensor.Axon',
- use_upnpc: bool = False,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False,
- ) -> bool:
- return serve_axon_extrinsic( self, axon, use_upnpc, wait_for_inclusion, wait_for_finalization)
-
- def serve_prometheus (
- self,
- wallet: 'bittensor.wallet',
- port: int,
- netuid: int,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- ) -> bool:
- return prometheus_extrinsic( self, wallet = wallet, port = port, netuid = netuid, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization)
- #################
- #### Staking ####
- #################
- def add_stake(
- self,
- wallet: 'bittensor.wallet',
- hotkey_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Adds the specified amount of stake to passed hotkey uid. """
- return add_stake_extrinsic(
- subtensor = self,
- wallet = wallet,
- hotkey_ss58 = hotkey_ss58,
- amount = amount,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt = prompt
- )
-
- def add_stake_multiple (
- self,
- wallet: 'bittensor.wallet',
- hotkey_ss58s: List[str],
- amounts: List[Union[Balance, float]] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Adds stake to each hotkey_ss58 in the list, using each amount, from a common coldkey."""
- return add_stake_multiple_extrinsic( self, wallet, hotkey_ss58s, amounts, wait_for_inclusion, wait_for_finalization, prompt)
-
- ###################
- #### Unstaking ####
- ###################
- def unstake_multiple (
- self,
- wallet: 'bittensor.wallet',
- hotkey_ss58s: List[str],
- amounts: List[Union[Balance, float]] = None,
- wait_for_inclusion: bool = True,
- wait_for_finalization: bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Removes stake from each hotkey_ss58 in the list, using each amount, to a common coldkey. """
- return unstake_multiple_extrinsic( self, wallet, hotkey_ss58s, amounts, wait_for_inclusion, wait_for_finalization, prompt)
-
-
-
- def unstake (
- self,
- wallet: 'bittensor.wallet',
- hotkey_ss58: Optional[str] = None,
- amount: Union[Balance, float] = None,
- wait_for_inclusion:bool = True,
- wait_for_finalization:bool = False,
- prompt: bool = False,
- ) -> bool:
- """ Removes stake into the wallet coldkey from the specified hotkey uid."""
- return unstake_extrinsic( self, wallet, hotkey_ss58, amount, wait_for_inclusion, wait_for_finalization, prompt )
-
-
- ########################
- #### Standard Calls ####
- ########################
-
- """ Queries subtensor named storage with params and block. """
- def query_subtensor( self, name: str, block: Optional[int] = None, params: Optional[List[object]] = [] ) -> Optional[object]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- return substrate.query(
- module='SubtensorModule',
- storage_function = name,
- params = params,
- block_hash = None if block == None else substrate.get_block_hash(block)
- )
- return make_substrate_call_with_retry()
-
- """ Queries subtensor map storage with params and block. """
- def query_map_subtensor( self, name: str, block: Optional[int] = None, params: Optional[List[object]] = [] ) -> Optional[object]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- return substrate.query_map(
- module='SubtensorModule',
- storage_function = name,
- params = params,
- block_hash = None if block == None else substrate.get_block_hash(block)
- )
- return make_substrate_call_with_retry()
-
- """ Gets a constant from subtensor with module_name, constant_name, and block. """
- def query_constant( self, module_name: str, constant_name: str, block: Optional[int] = None ) -> Optional[object]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- return substrate.get_constant(
- module_name=module_name,
- constant_name=constant_name,
- block_hash = None if block == None else substrate.get_block_hash(block)
- )
- return make_substrate_call_with_retry()
-
- #####################################
- #### Hyper parameter calls. ####
- #####################################
-
- """ Returns network Rho hyper parameter """
- def rho (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor( "Rho", block, [netuid] ).value
-
- """ Returns network Kappa hyper parameter """
- def kappa (self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- if not self.subnet_exists( netuid ): return None
- return U16_NORMALIZED_FLOAT( self.query_subtensor( "Kappa", block, [netuid] ).value )
-
- """ Returns network Difficulty hyper parameter """
- def difficulty (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor( "Difficulty", block, [netuid] ).value
-
- """ Returns network Burn hyper parameter """
- def burn (self, netuid: int, block: Optional[int] = None ) -> Optional[bittensor.Balance]:
- if not self.subnet_exists( netuid ): return None
- return bittensor.Balance.from_rao( self.query_subtensor( "Burn", block, [netuid] ).value )
-
- """ Returns network ImmunityPeriod hyper parameter """
- def immunity_period (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("ImmunityPeriod", block, [netuid] ).value
-
- """ Returns network ValidatorBatchSize hyper parameter """
- def validator_batch_size (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("ValidatorBatchSize", block, [netuid] ).value
-
- """ Returns network ValidatorPruneLen hyper parameter """
- def validator_prune_len (self, netuid: int, block: Optional[int] = None ) -> int:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("ValidatorPruneLen", block, [netuid] ).value
-
- """ Returns network ValidatorLogitsDivergence hyper parameter """
- def validator_logits_divergence (self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- if not self.subnet_exists( netuid ): return None
- return U16_NORMALIZED_FLOAT(self.query_subtensor("ValidatorLogitsDivergence", block, [netuid]).value)
-
- """ Returns network ValidatorSequenceLength hyper parameter """
- def validator_sequence_length (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("ValidatorSequenceLength", block, [netuid] ).value
-
- """ Returns network ValidatorEpochsPerReset hyper parameter """
- def validator_epochs_per_reset (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("ValidatorEpochsPerReset", block, [netuid] ).value
-
- """ Returns network ValidatorEpochLen hyper parameter """
- def validator_epoch_length (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("ValidatorEpochLen", block, [netuid] ).value
-
- """ Returns network ValidatorEpochLen hyper parameter """
- def validator_exclude_quantile (self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- if not self.subnet_exists( netuid ): return None
- return U16_NORMALIZED_FLOAT( self.query_subtensor("ValidatorExcludeQuantile", block, [netuid] ).value )
-
- """ Returns network MaxAllowedValidators hyper parameter """
- def max_allowed_validators(self, netuid: int, block: Optional[int] = None) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor( 'MaxAllowedValidators', block, [netuid] ).value
-
- """ Returns network MinAllowedWeights hyper parameter """
- def min_allowed_weights (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor("MinAllowedWeights", block, [netuid] ).value
-
- """ Returns network MaxWeightsLimit hyper parameter """
- def max_weight_limit (self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- if not self.subnet_exists( netuid ): return None
- return U16_NORMALIZED_FLOAT( self.query_subtensor('MaxWeightsLimit', block, [netuid] ).value )
-
- """ Returns network ScalingLawPower hyper parameter """
- def scaling_law_power (self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor('ScalingLawPower', block, [netuid] ).value / 100.
-
- """ Returns network SynergyScalingLawPower hyper parameter """
- def synergy_scaling_law_power (self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor('SynergyScalingLawPower', block, [netuid] ).value / 100.
-
- """ Returns network SubnetN hyper parameter """
- def subnetwork_n (self, netuid: int, block: Optional[int] = None ) -> int:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor('SubnetN', block, [netuid] ).value
-
- """ Returns network MaxAllowedUids hyper parameter """
- def max_n (self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor('MaxAllowedUids', block, [netuid] ).value
-
- """ Returns network BlocksSinceLastStep hyper parameter """
- def blocks_since_epoch (self, netuid: int, block: Optional[int] = None) -> int:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor('BlocksSinceLastStep', block, [netuid] ).value
-
- """ Returns network Tempo hyper parameter """
- def tempo (self, netuid: int, block: Optional[int] = None) -> int:
- if not self.subnet_exists( netuid ): return None
- return self.query_subtensor('Tempo', block, [netuid] ).value
-
- ##########################
- #### Account functions ###
- ##########################
-
- """ Returns the total stake held on a hotkey including delegative """
- def get_total_stake_for_hotkey( self, ss58_address: str, block: Optional[int] = None ) -> Optional['bittensor.Balance']:
- return bittensor.Balance.from_rao( self.query_subtensor( 'TotalHotkeyStake', block, [ss58_address] ).value )
-
- """ Returns the total stake held on a coldkey across all hotkeys including delegates"""
- def get_total_stake_for_coldkey( self, ss58_address: str, block: Optional[int] = None ) -> Optional['bittensor.Balance']:
- return bittensor.Balance.from_rao( self.query_subtensor( 'TotalColdkeyStake', block, [ss58_address] ).value )
-
- """ Returns the stake under a coldkey - hotkey pairing """
- def get_stake_for_coldkey_and_hotkey( self, hotkey_ss58: str, coldkey_ss58: str, block: Optional[int] = None ) -> Optional['bittensor.Balance']:
- return bittensor.Balance.from_rao( self.query_subtensor( 'Stake', block, [hotkey_ss58, coldkey_ss58] ).value )
-
- """ Returns a list of stake tuples (coldkey, balance) for each delegating coldkey including the owner"""
- def get_stake( self, hotkey_ss58: str, block: Optional[int] = None ) -> List[Tuple[str,'bittensor.Balance']]:
- return [ (r[0].value, bittensor.Balance.from_rao( r[1].value )) for r in self.query_map_subtensor( 'Stake', block, [hotkey_ss58] ) ]
-
- """ Returns true if the hotkey is known by the chain and there are accounts. """
- def does_hotkey_exist( self, hotkey_ss58: str, block: Optional[int] = None ) -> bool:
- return (self.query_subtensor( 'Owner', block, [hotkey_ss58 ] ).value != "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM")
-
- """ Returns the coldkey owner of the passed hotkey """
- def get_hotkey_owner( self, hotkey_ss58: str, block: Optional[int] = None ) -> Optional[str]:
- if self.does_hotkey_exist( hotkey_ss58, block ):
- return self.query_subtensor( 'Owner', block, [hotkey_ss58 ] ).value
- else:
- return None
-
- """ Returns the axon information for this hotkey account """
- def get_axon_info( self, hotkey_ss58: str, block: Optional[int] = None ) -> Optional[AxonInfo]:
- result = self.query_subtensor( 'Axons', block, [hotkey_ss58 ] )
- if result != None:
- return AxonInfo(
- ip = bittensor.utils.networking.ip_from_int( result.value.ip ),
- ip_type = result.value.ip_type,
- port = result.value.port,
- protocol = result.value.protocol,
- version = result.value.version,
- placeholder1 = result.value.placeholder1,
- placeholder2 = result.value.placeholder2,
- )
- else:
- return None
-
- """ Returns the prometheus information for this hotkey account """
- def get_prometheus_info( self, hotkey_ss58: str, block: Optional[int] = None ) -> Optional[AxonInfo]:
- result = self.query_subtensor( 'Prometheus', block, [hotkey_ss58 ] )
- if result != None:
- return PrometheusInfo (
- ip = bittensor.utils.networking.ip_from_int( result.value.ip ),
- ip_type = result.value.ip_type,
- port = result.value.port,
- version = result.value.version,
- block = result.value.block,
- )
- else:
- return None
-
- ###########################
- #### Global Parameters ####
- ###########################
-
- @property
- def block (self) -> int:
- r""" Returns current chain block.
- Returns:
- block (int):
- Current chain block.
- """
- return self.get_current_block()
-
- def total_issuance (self, block: Optional[int] = None ) -> 'bittensor.Balance':
- return bittensor.Balance.from_rao( self.query_subtensor( 'TotalIssuance', block ).value )
-
- def total_stake (self,block: Optional[int] = None ) -> 'bittensor.Balance':
- return bittensor.Balance.from_rao( self.query_subtensor( "TotalStake", block ).value )
-
- def serving_rate_limit (self, block: Optional[int] = None ) -> Optional[int]:
- return self.query_subtensor( "ServingRateLimit", block ).value
-
- #####################################
- #### Network Parameters ####
- #####################################
-
- def subnet_exists( self, netuid: int, block: Optional[int] = None ) -> bool:
- return self.query_subtensor( 'NetworksAdded', block, [netuid] ).value
-
- def get_all_subnet_netuids( self, block: Optional[int] = None ) -> List[int]:
- subnet_netuids = []
- result = self.query_map_subtensor( 'NetworksAdded', block )
- if result.records:
- for netuid, exists in result:
- if exists:
- subnet_netuids.append( netuid.value )
-
- return subnet_netuids
-
- def get_total_subnets( self, block: Optional[int] = None ) -> int:
- return self.query_subtensor( 'TotalSubnets', block ).value
-
- def get_subnet_modality( self, netuid: int, block: Optional[int] = None ) -> Optional[int]:
- return self.query_subtensor( 'NetworkModality', block, [netuid] ).value
-
- def get_subnet_connection_requirement( self, netuid_0: int, netuid_1: int, block: Optional[int] = None) -> Optional[int]:
- return self.query_subtensor( 'NetworkConnect', block, [netuid_0, netuid_1] ).value
-
- def get_emission_value_by_subnet( self, netuid: int, block: Optional[int] = None ) -> Optional[float]:
- return bittensor.Balance.from_rao( self.query_subtensor( 'EmissionValues', block, [ netuid ] ).value )
-
- def get_subnet_connection_requirements( self, netuid: int, block: Optional[int] = None) -> Dict[str, int]:
- result = self.query_map_subtensor( 'NetworkConnect', block, [netuid] )
- if result.records:
- requirements = {}
- for tuple in result.records:
- requirements[str(tuple[0].value)] = tuple[1].value
- else:
- return {}
-
- def get_burn(self, block: Optional[int] = None, netuid=3, ) -> Optional[float]:
- return self.query_subtensor( 'Burn', block, [netuid] ).value
-
- def get_subnets( self, block: Optional[int] = None ) -> List[int]:
- subnets = []
- result = self.query_map_subtensor( 'NetworksAdded', block )
- if result.records:
- for network in result.records:
- subnets.append( network[0].value )
- return subnets
- else:
- return []
-
- def get_all_subnets_info( self, block: Optional[int] = None ) -> List[SubnetInfo]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = []
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="subnetInfo_getSubnetsInfo", # custom rpc method
- params=params
- )
-
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return []
-
- return SubnetInfo.list_from_vec_u8( result )
-
- def get_subnet_info( self, netuid: int, block: Optional[int] = None ) -> Optional[SubnetInfo]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [netuid]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="subnetInfo_getSubnetInfo", # custom rpc method
- params=params
- )
-
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return None
-
- return SubnetInfo.from_vec_u8( result )
-
- ####################
- #### Nomination ####
- ####################
- def is_hotkey_delegate( self, hotkey_ss58: str ) -> bool:
- return hotkey_ss58 in [ info.hotkey_ss58 for info in self.get_delegates() ]
-
- def get_delegate_take( self, hotkey_ss58: str, block: Optional[int] = None ) -> Optional[float]:
- return U16_NORMALIZED_FLOAT( self.query_subtensor( 'Delegates', block, [ hotkey_ss58 ] ).value )
-
- def get_nominators_for_hotkey( self, hotkey_ss58: str, block: Optional[int] = None ) -> List[Tuple[str, Balance]]:
- result = self.query_map_subtensor( 'Stake', block, [ hotkey_ss58 ] )
- if result.records:
- return [(record[0].value, record[1].value) for record in result.records]
- else:
- return 0
-
- def get_delegate_by_hotkey( self, hotkey_ss58: str, block: Optional[int] = None ) -> Optional[DelegateInfo]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry(encoded_hotkey: List[int]):
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [encoded_hotkey]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="delegateInfo_getDelegate", # custom rpc method
- params=params
- )
-
- hotkey_bytes: bytes = bittensor.utils.ss58_address_to_bytes( hotkey_ss58 )
- encoded_hotkey: List[int] = [ int( byte ) for byte in hotkey_bytes ]
- json_body = make_substrate_call_with_retry(encoded_hotkey)
- result = json_body['result']
-
- if result in (None, []):
- return None
-
- return DelegateInfo.from_vec_u8( result )
-
- def get_delegates( self, block: Optional[int] = None ) -> List[DelegateInfo]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = []
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="delegateInfo_getDelegates", # custom rpc method
- params=params
- )
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return []
-
- return DelegateInfo.list_from_vec_u8( result )
-
- def get_delegated( self, coldkey_ss58: str, block: Optional[int] = None ) -> List[Tuple[DelegateInfo, Balance]]:
- """ Returns the list of delegates that a given coldkey is staked to.
- """
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry(encoded_coldkey: List[int]):
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [encoded_coldkey]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="delegateInfo_getDelegated", # custom rpc method
- params=params
- )
-
- coldkey_bytes: bytes = bittensor.utils.ss58_address_to_bytes( coldkey_ss58 )
- encoded_coldkey: List[int] = [ int( byte ) for byte in coldkey_bytes ]
- json_body = make_substrate_call_with_retry(encoded_coldkey)
- result = json_body['result']
-
- if result in (None, []):
- return []
-
- return DelegateInfo.delegated_list_from_vec_u8( result )
-
-
- ########################################
- #### Neuron information per subnet ####
- ########################################
-
- def is_hotkey_registered_any( self, hotkey_ss58: str, block: Optional[int] = None) -> bool:
- return len( self.get_netuids_for_hotkey( hotkey_ss58, block) ) > 0
-
- def is_hotkey_registered_on_subnet( self, hotkey_ss58: str, netuid: int, block: Optional[int] = None) -> bool:
- return self.get_uid_for_hotkey_on_subnet( hotkey_ss58, netuid, block ) != None
-
- def is_hotkey_registered( self, hotkey_ss58: str, netuid: int, block: Optional[int] = None) -> bool:
- return self.get_uid_for_hotkey_on_subnet( hotkey_ss58, netuid, block ) != None
-
- def get_uid_for_hotkey_on_subnet( self, hotkey_ss58: str, netuid: int, block: Optional[int] = None) -> int:
- return self.query_subtensor( 'Uids', block, [ netuid, hotkey_ss58 ] ).value
-
- def get_all_uids_for_hotkey( self, hotkey_ss58: str, block: Optional[int] = None) -> List[int]:
- return [ self.get_uid_for_hotkey_on_subnet( hotkey_ss58, netuid, block) for netuid in self.get_netuids_for_hotkey( hotkey_ss58, block)]
-
- def get_netuids_for_hotkey( self, hotkey_ss58: str, block: Optional[int] = None) -> List[int]:
- result = self.query_map_subtensor( 'IsNetworkMember', block, [ hotkey_ss58 ] )
- netuids = []
- for netuid, is_member in result.records:
- if is_member:
- netuids.append( netuid.value )
- return netuids
-
- def get_neuron_for_pubkey_and_subnet( self, hotkey_ss58: str, netuid: int, block: Optional[int] = None ) -> Optional[NeuronInfo]:
- return self.neuron_for_uid( self.get_uid_for_hotkey_on_subnet(hotkey_ss58, netuid, block=block), netuid, block = block)
-
- def get_all_neurons_for_pubkey( self, hotkey_ss58: str, block: Optional[int] = None ) -> List[NeuronInfo]:
- netuids = self.get_netuids_for_hotkey( hotkey_ss58, block)
- uids = [self.get_uid_for_hotkey_on_subnet(hotkey_ss58, net) for net in netuids]
- return [self.neuron_for_uid( uid, net ) for uid, net in list(zip(uids, netuids))]
-
- def neuron_has_validator_permit( self, uid: int, netuid: int, block: Optional[int] = None ) -> Optional[bool]:
- return self.query_subtensor( 'ValidatorPermit', block, [ netuid, uid ] ).value
-
- def neuron_for_wallet( self, wallet: 'bittensor.Wallet', netuid = int, block: Optional[int] = None ) -> Optional[NeuronInfo]:
- return self.get_neuron_for_pubkey_and_subnet ( wallet.hotkey.ss58_address, netuid = netuid, block = block )
-
- def neuron_for_uid( self, uid: int, netuid: int, block: Optional[int] = None ) -> Optional[NeuronInfo]:
- r""" Returns a list of neuron from the chain.
- Args:
- uid ( int ):
- The uid of the neuron to query for.
- netuid ( int ):
- The uid of the network to query for.
- block ( int ):
- The neuron at a particular block
- Returns:
- neuron (Optional[NeuronInfo]):
- neuron metadata associated with uid or None if it does not exist.
- """
- if uid == None: return NeuronInfo._null_neuron()
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [netuid, uid]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="neuronInfo_getNeuron", # custom rpc method
- params=params
- )
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return NeuronInfo._null_neuron()
-
- return NeuronInfo.from_vec_u8( result )
-
- def neurons(self, netuid: int, block: Optional[int] = None ) -> List[NeuronInfo]:
- r""" Returns a list of neuron from the chain.
- Args:
- netuid ( int ):
- The netuid of the subnet to pull neurons from.
- block ( Optional[int] ):
- block to sync from.
- Returns:
- neuron (List[NeuronInfo]):
- List of neuron metadata objects.
- """
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [netuid]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="neuronInfo_getNeurons", # custom rpc method
- params=params
- )
-
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return []
-
- return NeuronInfo.list_from_vec_u8( result )
-
- def neuron_for_uid_lite( self, uid: int, netuid: int, block: Optional[int] = None ) -> Optional[NeuronInfoLite]:
- r""" Returns a list of neuron lite from the chain.
- Args:
- uid ( int ):
- The uid of the neuron to query for.
- netuid ( int ):
- The uid of the network to query for.
- block ( int ):
- The neuron at a particular block
- Returns:
- neuron (Optional[NeuronInfoLite]):
- neuron metadata associated with uid or None if it does not exist.
- """
- if uid == None: return NeuronInfoLite._null_neuron()
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [netuid, uid]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="neuronInfo_getNeuronLite", # custom rpc method
- params=params
- )
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return NeuronInfoLite._null_neuron()
-
- return NeuronInfoLite.from_vec_u8( result )
-
- def neurons_lite(self, netuid: int, block: Optional[int] = None ) -> List[NeuronInfoLite]:
- r""" Returns a list of neuron lite from the chain.
- Args:
- netuid ( int ):
- The netuid of the subnet to pull neurons from.
- block ( Optional[int] ):
- block to sync from.
- Returns:
- neuron (List[NeuronInfoLite]):
- List of neuron lite metadata objects.
- """
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- block_hash = None if block == None else substrate.get_block_hash( block )
- params = [netuid]
- if block_hash:
- params = params + [block_hash]
- return substrate.rpc_request(
- method="neuronInfo_getNeuronsLite", # custom rpc method
- params=params
- )
-
- json_body = make_substrate_call_with_retry()
- result = json_body['result']
-
- if result in (None, []):
- return []
-
- return NeuronInfoLite.list_from_vec_u8( result )
-
- def metagraph( self, netuid: int, block: Optional[int] = None, lite: bool = True ) -> 'bittensor.Metagraph':
- r""" Returns the metagraph for the subnet.
- Args:
- netuid ( int ):
- The network uid of the subnet to query.
- block (Optional[int]):
- The block to create the metagraph for.
- Defaults to latest.
- lite (bool, default=True):
- If true, returns a metagraph using the lite sync (no weights, no bonds)
- Returns:
- metagraph ( `bittensor.Metagraph` ):
- The metagraph for the subnet at the block.
- """
- status: Optional['rich.console.Status'] = None
- if bittensor.__use_console__:
- status = bittensor.__console__.status("Synchronizing Metagraph...", spinner="earth")
- status.start()
-
- # Get neurons.
- if lite:
- neurons = self.neurons_lite( netuid = netuid, block = block )
- else:
- neurons = self.neurons( netuid = netuid, block = block )
-
- # Get subnet info.
- subnet_info: Optional[bittensor.SubnetInfo] = self.get_subnet_info( netuid = netuid, block = block )
- if subnet_info == None:
- status.stop() if status else ...
- raise ValueError('Could not find subnet info for netuid: {}'.format(netuid))
-
- status.stop() if status else ...
-
- # Create metagraph.
- block_number = self.block
-
- metagraph = bittensor.metagraph.from_neurons( network = self.network, netuid = netuid, info = subnet_info, neurons = neurons, block = block_number )
- print("Metagraph subtensor: ", self.network)
- return metagraph
-
- ################
- #### Transfer ##
- ################
-
-
-
-
- ################
- #### Legacy ####
- ################
-
- def get_balance(self, address: str, block: int = None) -> Balance:
- r""" Returns the token balance for the passed ss58_address address
- Args:
- address (Substrate address format, default = 42):
- ss58 chain address.
- Return:
- balance (bittensor.utils.balance.Balance):
- account balance
- """
- try:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- return substrate.query(
- module='System',
- storage_function='Account',
- params=[address],
- block_hash = None if block == None else substrate.get_block_hash( block )
- )
- result = make_substrate_call_with_retry()
- except scalecodec.exceptions.RemainingScaleBytesNotEmptyException:
- logger.critical("Your wallet it legacy formatted, you need to run btcli stake --ammount 0 to reformat it." )
- return Balance(1000)
- return Balance( result.value['data']['free'] )
-
- def get_current_block(self) -> int:
- r""" Returns the current block number on the chain.
- Returns:
- block_number (int):
- Current chain blocknumber.
- """
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- return substrate.get_block_number(None)
- return make_substrate_call_with_retry()
-
- def get_balances(self, block: int = None) -> Dict[str, Balance]:
- @retry(delay=2, tries=3, backoff=2, max_delay=4)
- def make_substrate_call_with_retry():
- with self.substrate as substrate:
- return substrate.query_map(
- module='System',
- storage_function='Account',
- block_hash = None if block == None else substrate.get_block_hash( block )
- )
- result = make_substrate_call_with_retry()
- return_dict = {}
- for r in result:
- bal = bittensor.Balance( int( r[1]['data']['free'].value ) )
- return_dict[r[0].value] = bal
- return return_dict
-
- @staticmethod
- def _null_neuron() -> NeuronInfo:
- neuron = NeuronInfo(
- uid = 0,
- netuid = 0,
- active = 0,
- stake = '0',
- rank = 0,
- emission = 0,
- incentive = 0,
- consensus = 0,
- trust = 0,
- validator_trust = 0,
- dividends = 0,
- last_update = 0,
- validator_permit = False,
- weights = [],
- bonds = [],
- prometheus_info = None,
- axon_info = None,
- is_null = True,
- coldkey = "000000000000000000000000000000000000000000000000",
- hotkey = "000000000000000000000000000000000000000000000000"
- )
- return neuron
diff --git a/commune/modules/bittensor/subtensor/subtensor_mock.py b/commune/modules/bittensor/subtensor/subtensor_mock.py
deleted file mode 100644
index 6c3a15ebb..000000000
--- a/commune/modules/bittensor/subtensor/subtensor_mock.py
+++ /dev/null
@@ -1,341 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2022 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-from substrateinterface import SubstrateInterface, Keypair
-from scalecodec import GenericCall
-import psutil
-import subprocess
-from sys import platform
-import bittensor
-import time
-import os
-from typing import Optional, Tuple, Dict, Union
-import requests
-
-from . import subtensor_impl
-
-__type_registery__ = {
- "runtime_id": 2,
- "types": {
- "Balance": "u64",
- "NeuronMetadataOf": {
- "type": "struct",
- "type_mapping": [
- ["version", "u32"],
- ["ip", "u128"],
- ["port", "u16"],
- ["ip_type", "u8"],
- ["uid", "u32"],
- ["modality", "u8"],
- ["hotkey", "AccountId"],
- ["coldkey", "AccountId"],
- ["active", "bool"],
- ["last_update", "u64"],
- ["validator_permit", "bool"],
- ["stake", "u64"],
- ["rank", "u16"],
- ["trust", "u16"],
- ["consensus", "u16"],
- ["validator_trust", "u16"],
- ["incentive", "u16"],
- ["dividends", "u16"],
- ["emission", "u64"],
- ["bonds", "Vec<(u16, u16)>"],
- ["weights", "Vec<(u16, u16)>"]
- ]
- }
- }
-}
-
-GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME = "node-subtensor"
-
-class mock_subtensor():
- r""" Returns a subtensor connection interface to a mocked subtensor process running in the background.
- Optionall creates the background process if it does not exist.
- """
-
- @classmethod
- def mock(cls):
-
- if not cls.global_mock_process_is_running():
- # Remove any old chain db
- if os.path.exists(bittensor.__mock_chain_db__):
- os.system(f'rm -rf {bittensor.__mock_chain_db__}')
- _owned_mock_subtensor_process = cls.create_global_mock_process()
- else:
- _owned_mock_subtensor_process = None
- print ('Mock subtensor already running.')
-
- endpoint = bittensor.__mock_entrypoint__
- port = int(endpoint.split(':')[1])
- substrate = SubstrateInterface(
- ss58_format = bittensor.__ss58_format__,
- type_registry_preset='substrate-node-template',
- type_registry = __type_registery__,
- url = "ws://{}".format('localhost:{}'.format(port)),
- use_remote_preset=True
- )
- subtensor = Mock_Subtensor(
- substrate = substrate,
- network = 'mock',
- chain_endpoint = 'localhost:{}'.format(port),
-
- # Is mocked, optionally has owned process for ref counting.
- _is_mocked = True,
- _owned_mock_subtensor_process = _owned_mock_subtensor_process
- )
- return subtensor
-
- @classmethod
- def global_mock_process_is_running(cle) -> bool:
- r""" If subtensor is running a mock process this kills the mock.
- """
- for p in psutil.process_iter():
- if p.name() == GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME and p.parent().pid == os.getpid() and p.status() != psutil.STATUS_ZOMBIE and p.status() != psutil.STATUS_DEAD:
- print(f"Found process with name {p.name()}, parent {p.parent().pid} status {p.status()} and pid {p.pid}")
- return True
- return False
-
- @classmethod
- def kill_global_mock_process(self):
- r""" Kills the global mocked subtensor process even if not owned.
- """
- for p in psutil.process_iter():
- if p.name() == GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME and p.parent().pid == os.getpid() :
- p.terminate()
- p.kill()
- time.sleep(2) # Buffer to ensure the processes actually die
-
- @classmethod
- def create_global_mock_process(self):
- r""" Creates a global mocked subtensor process running in the backgroun with name GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME.
- """
- try:
- operating_system = "OSX" if platform == "darwin" else "Linux"
- path = "./tests/mock_subtensor/bin/{}/{}".format(operating_system, GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME)
-
- ws_port = int(bittensor.__mock_entrypoint__.split(':')[1])
- print(f'MockSub ws_port: {ws_port}')
-
- command_args = [ path ] + f'--chain dev --base-path {bittensor.__mock_chain_db__} --execution native --ws-max-connections 1000 --no-mdns --rpc-cors all'.split(' ') + \
- f'--port {int(bittensor.get_random_unused_port())} --rpc-port {int(bittensor.get_random_unused_port())} --ws-port {ws_port}'.split(' ') + \
- '--validator --alice'.split(' ')
-
- print ('Starting subtensor process with command: {}'.format(command_args))
-
- _mock_subtensor_process = subprocess.Popen(
- command_args,
- close_fds=True, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
-
- # Wait for the process to start. Check for errors.
- try:
- # Timeout is okay.
- error_code = _mock_subtensor_process.wait(timeout=3)
- except subprocess.TimeoutExpired:
- error_code = None
-
- if error_code is not None:
- raise RuntimeError( 'Failed to start mocked subtensor process: {}'.format(error_code) )
-
- print ('Starting subtensor process with pid {} and name {}'.format(_mock_subtensor_process.pid, GLOBAL_SUBTENSOR_MOCK_PROCESS_NAME))
-
- errored: bool = True
- while errored:
- errored = False
- try:
- _ = requests.get('http://localhost:{}'.format(ws_port))
- except requests.exceptions.ConnectionError as e:
- errored = True
- time.sleep(0.5) # Wait for the process to start.
-
- return _mock_subtensor_process
- except Exception as e:
- raise RuntimeError( 'Failed to start mocked subtensor process: {}'.format(e) )
-
-
-class Mock_Subtensor(subtensor_impl.Subtensor):
- """
- Handles interactions with the subtensor chain.
- """
- sudo_keypair: Keypair = Keypair.create_from_uri('//Alice') # Alice is the sudo keypair for the mock chain.
-
- def __init__(
- self,
- _is_mocked: bool,
- _owned_mock_subtensor_process: object,
- **kwargs,
- ):
- r""" Initializes a subtensor chain interface.
- Args:
- _owned_mock_subtensor_process (Used for testing):
- a subprocess where a mock chain is running.
- """
- super().__init__(**kwargs)
- # Exclusively used to mock a connection to our chain.
- self._owned_mock_subtensor_process = _owned_mock_subtensor_process
- self._is_mocked = _is_mocked
-
- print("---- MOCKED SUBTENSOR INITIALIZED ----")
-
- def __str__(self) -> str:
- if self._is_mocked == True and self._owned_mock_subtensor_process != None:
- # Mocked and owns background process.
- return "MockSubtensor({}, PID:{})".format( self.chain_endpoint, self._owned_mock_subtensor_process.pid)
- else:
- # Mocked but does not own process.
- return "MockSubtensor({})".format( self.chain_endpoint)
-
- def __del__(self):
- self.optionally_kill_owned_mock_instance()
-
- def __exit__(self):
- pass
-
- def optionally_kill_owned_mock_instance(self):
- r""" If this subtensor instance owns the mock process, it kills the process.
- """
- if self._owned_mock_subtensor_process != None:
- try:
- self._owned_mock_subtensor_process.terminate()
- self._owned_mock_subtensor_process.kill()
- os.system("kill %i" % self._owned_mock_subtensor_process.pid)
- time.sleep(2) # Buffer to ensure the processes actually die
- except Exception as e:
- print(f"failed to kill owned mock instance: {e}")
- # Occasionally
- pass
-
- def wrap_sudo(self, call: GenericCall) -> GenericCall:
- r""" Wraps a call in a sudo call.
- """
- return self.substrate.compose_call(
- call_module='Sudo',
- call_function='sudo',
- call_params = {
- 'call': call.value
- }
- )
-
- def sudo_force_set_balance(self, ss58_address: str, balance: Union['bittensor.Balance', int, float], ) -> Tuple[bool, Optional[str]]:
- r""" Sets the balance of an account using the sudo key.
- """
- if isinstance(balance, bittensor.Balance):
- balance = balance.rao
- elif isinstance(balance, float):
- balance = int(balance * bittensor.utils.RAOPERTAO)
- elif isinstance(balance, int):
- pass
- else:
- raise ValueError('Invalid type for balance: {}'.format(type(balance)))
-
- with self.substrate as substrate:
- call = substrate.compose_call(
- call_module='Balances',
- call_function='set_balance',
- call_params = {
- 'who': ss58_address,
- 'new_free': balance,
- 'new_reserved': 0
- }
- )
-
- wrapped_call = self.wrap_sudo(call)
-
- extrinsic = substrate.create_signed_extrinsic( call = wrapped_call, keypair = self.sudo_keypair )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = True, wait_for_finalization = True )
-
- response.process_events()
- if response.is_success:
- return True, None
- else:
- return False, response.error_message
-
- def sudo_set_difficulty(self, netuid: int, difficulty: int) -> Tuple[bool, Optional[str]]:
- r""" Sets the difficulty of the mock chain using the sudo key.
- """
- with self.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='sudo_set_difficulty',
- call_params = {
- 'netuid': netuid,
- 'difficulty': difficulty
- }
- )
-
- wrapped_call = self.wrap_sudo(call)
-
- extrinsic = substrate.create_signed_extrinsic( call = wrapped_call, keypair = self.sudo_keypair )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = True, wait_for_finalization = True )
-
- response.process_events()
- if response.is_success:
- return True, None
- else:
- return False, response.error_message
-
- def sudo_add_network(self, netuid: int, tempo: int = 0, modality: int = 0) -> Tuple[bool, Optional[str]]:
- r""" Adds a network to the mock chain using the sudo key.
- """
- with self.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='sudo_add_network',
- call_params = {
- 'netuid': netuid,
- 'tempo': tempo,
- 'modality': modality
- }
- )
-
- wrapped_call = self.wrap_sudo(call)
-
- extrinsic = substrate.create_signed_extrinsic( call = wrapped_call, keypair = self.sudo_keypair )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = True, wait_for_finalization = True )
-
- response.process_events()
- if response.is_success:
- return True, None
- else:
- return False, response.error_message
-
- def sudo_register(self, netuid: int, hotkey: str, coldkey: str, stake: int = 0, balance: int = 0) -> Tuple[bool, Optional[str]]:
- r""" Registers a neuron to the subnet using sudo.
- """
- with self.substrate as substrate:
- call = substrate.compose_call(
- call_module='SubtensorModule',
- call_function='sudo_register',
- call_params = {
- 'netuid': netuid,
- 'hotkey': hotkey,
- 'coldkey': coldkey,
- 'stake': stake,
- 'balance': balance
- }
- )
-
- wrapped_call = self.wrap_sudo(call)
-
- extrinsic = substrate.create_signed_extrinsic( call = wrapped_call, keypair = self.sudo_keypair )
- response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = True, wait_for_finalization = True )
-
- response.process_events()
- if response.is_success:
- return True, None
- else:
- return False, response.error_message
\ No newline at end of file
diff --git a/commune/modules/bittensor/tasks/register.py b/commune/modules/bittensor/tasks/register.py
deleted file mode 100644
index 8c212676d..000000000
--- a/commune/modules/bittensor/tasks/register.py
+++ /dev/null
@@ -1,8 +0,0 @@
-
-import commune
-
-if __name__ == "__main__":
-
- api = commune.api()
- block = api.launch('block.bittensor', fn='register_loop',mode='pm2', kwargs=dict(subtensor='nobunaga'), name='register_loop_test')
- # print(api.pm2_list())
diff --git a/commune/modules/bittensor/utils/__init__.py b/commune/modules/bittensor/utils/__init__.py
deleted file mode 100644
index baff69030..000000000
--- a/commune/modules/bittensor/utils/__init__.py
+++ /dev/null
@@ -1,247 +0,0 @@
-import numbers
-from typing import Callable, Union
-
-import bittensor
-import pandas
-import requests
-import torch
-import scalecodec
-from substrateinterface import Keypair
-from .registration import *
-
-RAOPERTAO = 1e9
-U16_MAX = 65535
-U64_MAX = 18446744073709551615
-
-def indexed_values_to_dataframe (
- prefix: Union[str, int],
- index: Union[list, torch.LongTensor],
- values: Union[list, torch.Tensor],
- filter_zeros: bool = False
- ) -> 'pandas.DataFrame':
- # Type checking.
- if not isinstance(prefix, str) and not isinstance(prefix, numbers.Number):
- raise ValueError('Passed prefix must have type str or Number')
- if isinstance(prefix, numbers.Number):
- prefix = str(prefix)
- if not isinstance(index, list) and not isinstance(index, torch.Tensor):
- raise ValueError('Passed uids must have type list or torch.Tensor')
- if not isinstance(values, list) and not isinstance(values, torch.Tensor):
- raise ValueError('Passed values must have type list or torch.Tensor')
- if not isinstance(index, list):
- index = index.tolist()
- if not isinstance(values, list):
- values = values.tolist()
-
- index = [ idx_i for idx_i in index if idx_i < len(values) and idx_i >= 0 ]
- dataframe = pandas.DataFrame(columns=[prefix], index = index )
- for idx_i in index:
- value_i = values[ idx_i ]
- if value_i > 0 or not filter_zeros:
- dataframe.loc[idx_i] = pandas.Series( { str(prefix): value_i } )
- return dataframe
-
-
-def unbiased_topk( values, k, dim=0, sorted = True, largest = True):
- r""" Selects topk as in torch.topk but does not bias lower indices when values are equal.
- Args:
- values: (torch.Tensor)
- Values to index into.
- k: (int):
- Number to take.
-
- Return:
- topk: (torch.Tensor):
- topk k values.
- indices: (torch.LongTensor)
- indices of the topk values.
- """
- permutation = torch.randperm(values.shape[ dim ])
- permuted_values = values[ permutation ]
- topk, indices = torch.topk( permuted_values, k, dim = dim, sorted=sorted, largest=largest )
- return topk, permutation[ indices ]
-
-
-def version_checking():
- response = requests.get(bittensor.__pipaddress__)
- latest_version = response.json()['info']['version']
- version_split = latest_version.split(".")
- latest_version_as_int = (100 * int(version_split[0])) + (10 * int(version_split[1])) + (1 * int(version_split[2]))
-
- if latest_version_as_int > bittensor.__version_as_int__:
- print('\u001b[33mBittensor Version: Current {}/Latest {}\nPlease update to the latest version at your earliest convenience\u001b[0m'.format(bittensor.__version__,latest_version))
-
-@staticmethod
-def is_valid_ss58_address( address: str, valid_ss58_format=42 ) -> bool:
- """
- Checks if the given address is a valid ss58 address.
-
- Args:
- address(str): The address to check.
-
- Returns:
- True if the address is a valid ss58 address for Bittensor, False otherwise.
- """
- from substrateinterface.utils import ss58
- try:
- return ss58.is_valid_ss58_address( address, valid_ss58_format=valid_ss58_format ) # Default substrate ss58 format (legacy)
- except (IndexError):
- return False
-
-def is_valid_ed25519_pubkey( public_key: Union[str, bytes] ) -> bool:
- """
- Checks if the given public_key is a valid ed25519 key.
-
- Args:
- public_key(Union[str, bytes]): The public_key to check.
-
- Returns:
- True if the public_key is a valid ed25519 key, False otherwise.
-
- """
- from substrateinterface.utils import ss58
-
- try:
- if isinstance( public_key, str ):
- if len(public_key) != 64 and len(public_key) != 66:
- raise ValueError( "a public_key should be 64 or 66 characters" )
- elif isinstance( public_key, bytes ):
- if len(public_key) != 32:
- raise ValueError( "a public_key should be 32 bytes" )
- else:
- raise ValueError( "public_key must be a string or bytes" )
-
- keypair = Keypair(
- public_key=public_key,
- ss58_format=bittensor.__ss58_format__
- )
-
- ss58_addr = keypair.ss58_address
- return ss58_addr is not None
-
- except (ValueError, IndexError):
- return False
-
-def is_valid_bittensor_address_or_public_key( address: Union[str, bytes] ) -> bool:
- """
- Checks if the given address is a valid destination address.
-
- Args:
- address(Union[str, bytes]): The address to check.
-
- Returns:
- True if the address is a valid destination address, False otherwise.
- """
- if isinstance( address, str ):
- # Check if ed25519
- if address.startswith('0x'):
- return is_valid_ed25519_pubkey( address )
- else:
- # Assume ss58 address
- return is_valid_ss58_address( address )
- elif isinstance( address, bytes ):
- # Check if ed25519
- return is_valid_ed25519_pubkey( address )
- else:
- # Invalid address type
- return False
-
-def get_ss58_format( ss58_address: str ) -> int:
- """Returns the ss58 format of the given ss58 address."""
- return ss58.get_ss58_format( ss58_address )
-
-def strtobool_with_default( default: bool ) -> Callable[[str], bool]:
- """
- Creates a strtobool function with a default value.
-
- Args:
- default(bool): The default value to return if the string is empty.
-
- Returns:
- The strtobool function with the default value.
- """
- return lambda x: strtobool(x) if x != "" else default
-
-
-def strtobool(val: str) -> bool:
- """
- Converts a string to a boolean value.
-
- truth-y values are 'y', 'yes', 't', 'true', 'on', and '1';
- false-y values are 'n', 'no', 'f', 'false', 'off', and '0'.
-
- Raises ValueError if 'val' is anything else.
- """
- val = val.lower()
- if val in ('y', 'yes', 't', 'true', 'on', '1'):
- return True
- elif val in ('n', 'no', 'f', 'false', 'off', '0'):
- return False
- else:
- raise ValueError("invalid truth value %r" % (val,))
-
-def get_explorer_root_url_by_network_from_map(network: str, network_map: Dict[str, str]) -> Optional[str]:
- r"""
- Returns the explorer root url for the given network name from the given network map.
-
- Args:
- network(str): The network to get the explorer url for.
- network_map(Dict[str, str]): The network map to get the explorer url from.
-
- Returns:
- The explorer url for the given network.
- Or None if the network is not in the network map.
- """
- explorer_url: Optional[str] = None
- if network in network_map:
- explorer_url = network_map[network]
-
- return explorer_url
-
-
-def get_explorer_url_for_network(network: str, block_hash: str, network_map: Dict[str, str]) -> Optional[str]:
- r"""
- Returns the explorer url for the given block hash and network.
-
- Args:
- network(str): The network to get the explorer url for.
- block_hash(str): The block hash to get the explorer url for.
- network_map(Dict[str, str]): The network map to get the explorer url from.
-
- Returns:
- The explorer url for the given block hash and network.
- Or None if the network is not known.
- """
-
- explorer_url: Optional[str] = None
- # Will be None if the network is not known. i.e. not in network_map
- explorer_root_url: Optional[str] = get_explorer_root_url_by_network_from_map(network, network_map)
-
- if explorer_root_url is not None:
- # We are on a known network.
- explorer_url = "{root_url}/query/{block_hash}".format( root_url=explorer_root_url, block_hash = block_hash )
-
- return explorer_url
-
-def ss58_address_to_bytes(ss58_address: str) -> bytes:
- """Converts a ss58 address to a bytes object."""
- account_id_hex: str = scalecodec.ss58_decode(ss58_address, bittensor.__ss58_format__)
- return bytes.fromhex(account_id_hex)
-
-def U16_NORMALIZED_FLOAT( x: int ) -> float:
- return float( x ) / float( U16_MAX )
-
-def U64_NORMALIZED_FLOAT( x: int ) -> float:
- return float( x ) / float( U64_MAX )
-
-def u8_key_to_ss58(u8_key: List[int]) -> str:
-
- r"""
- Converts a u8-encoded account key to an ss58 address.
-
- Args:
- u8_key (List[int]): The u8-encoded account key.
- """
- import scalecodec
- # First byte is length, then 32 bytes of key.
- return scalecodec.ss58_encode( bytes(u8_key).hex(), bittensor.__ss58_format__)
diff --git a/commune/modules/bittensor/utils/balance.py b/commune/modules/bittensor/utils/balance.py
deleted file mode 100644
index 83af5790a..000000000
--- a/commune/modules/bittensor/utils/balance.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-from typing import Union
-
-import bittensor
-
-class Balance:
- """
- Represents the bittensor balance of the wallet, stored as rao (int)
- The Balance object is immutable, and can be used as a number or as a string
- Can only guarantee that the balance is accurate to 9 decimal places (tao)
-
- Note: In operations between Balance and int/float, the other value is assumed to be in rao
- """
-
- unit: str = bittensor.__tao_symbol__ # This is the tao unit
- rao_unit: str = bittensor.__rao_symbol__ # This is the rao unit
- rao: int
- tao: float
-
- def __init__(self, balance: Union[int, float]):
- if isinstance(balance, int):
- self.rao = balance
- elif isinstance(balance, float):
- # Assume tao value for the float
- self.rao = int(balance * pow(10, 9))
- else:
- raise TypeError("balance must be an int (rao) or a float (tao)")
-
- @property
- def tao(self):
- return self.rao / pow(10, 9)
-
- def __int__(self):
- return self.rao
-
- def __float__(self):
- return self.tao
-
- def __str__(self):
- return f"{self.unit}{float(self.tao):,.9f}"
-
- def __rich__(self):
- return "[green]{}[/green][green]{}[/green][green].[/green][dim green]{}[/dim green]".format(
- self.unit,
- format(float(self.tao), "f").split(".")[0],
- format(float(self.tao), "f").split(".")[1],
- )
-
- def __str_rao__(self):
- return f"{self.rao_unit}{int(self.rao)}"
-
- def __rich_rao__(self):
- return f"[green]{self.rao_unit}{int(self.rao)}[/green]"
-
- def __repr__(self):
- return self.__str__()
-
- def __eq__(self, other: Union[int, float, "Balance"]):
- if other is None:
- return False
-
- if hasattr(other, "rao"):
- return self.rao == other.rao
- else:
- try:
- # Attempt to cast to int from rao
- other_rao = int(other)
- return self.rao == other_rao
- except (TypeError, ValueError):
- raise NotImplementedError("Unsupported type")
-
- def __ne__(self, other: Union[int, float, "Balance"]):
- return not self == other
-
- def __gt__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return self.rao > other.rao
- else:
- try:
- # Attempt to cast to int from rao
- other_rao = int(other)
- return self.rao > other_rao
- except ValueError:
- raise NotImplementedError("Unsupported type")
-
- def __lt__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return self.rao < other.rao
- else:
- try:
- # Attempt to cast to int from rao
- other_rao = int(other)
- return self.rao < other_rao
- except ValueError:
- raise NotImplementedError("Unsupported type")
-
- def __le__(self, other: Union[int, float, "Balance"]):
- try:
- return self < other or self == other
- except (TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __ge__(self, other: Union[int, float, "Balance"]):
- try:
- return self > other or self == other
- except (TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __add__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return Balance.from_rao(int(self.rao + other.rao))
- else:
- try:
- # Attempt to cast to int from rao
- return Balance.from_rao(int(self.rao + other))
- except (ValueError, TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __radd__(self, other: Union[int, float, "Balance"]):
- try:
- return self + other
- except (TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __sub__(self, other: Union[int, float, "Balance"]):
- try:
- return self + -other
- except (TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __rsub__(self, other: Union[int, float, "Balance"]):
- try:
- return -self + other
- except (TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __mul__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return Balance.from_rao(int(self.rao * other.rao))
- else:
- try:
- # Attempt to cast to int from rao
- return Balance.from_rao(int(self.rao * other))
- except (ValueError, TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __rmul__(self, other: Union[int, float, "Balance"]):
- return self * other
-
- def __truediv__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return Balance.from_rao(int(self.rao / other.rao))
- else:
- try:
- # Attempt to cast to int from rao
- return Balance.from_rao(int(self.rao / other))
- except (ValueError, TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __rtruediv__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return Balance.from_rao(int(other.rao / self.rao))
- else:
- try:
- # Attempt to cast to int from rao
- return Balance.from_rao(int(other / self.rao))
- except (ValueError, TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __floordiv__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return Balance.from_rao(int(self.tao // other.tao))
- else:
- try:
- # Attempt to cast to int from rao
- return Balance.from_rao(int(self.rao // other))
- except (ValueError, TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __rfloordiv__(self, other: Union[int, float, "Balance"]):
- if hasattr(other, "rao"):
- return Balance.from_rao(int(other.rao // self.rao))
- else:
- try:
- # Attempt to cast to int from rao
- return Balance.from_rao(int(other // self.rao))
- except (ValueError, TypeError):
- raise NotImplementedError("Unsupported type")
-
- def __int__(self) -> int:
- return self.rao
-
- def __float__(self) -> float:
- return self.tao
-
- def __nonzero__(self) -> bool:
- return bool(self.rao)
-
- def __neg__(self):
- return Balance.from_rao(-self.rao)
-
- def __pos__(self):
- return Balance.from_rao(self.rao)
-
- def __abs__(self):
- return Balance.from_rao(abs(self.rao))
-
- @staticmethod
- def from_float(amount: float):
- """Given tao (float), return Balance object with rao(int) and tao(float), where rao = int(tao*pow(10,9))"""
- rao = int(amount * pow(10, 9))
- return Balance(rao)
-
- @staticmethod
- def from_tao(amount: float):
- """Given tao (float), return Balance object with rao(int) and tao(float), where rao = int(tao*pow(10,9))"""
- rao = int(amount * pow(10, 9))
- return Balance(rao)
-
- @staticmethod
- def from_rao(amount: int):
- """Given rao (int), return Balance object with rao(int) and tao(float), where rao = int(tao*pow(10,9))"""
- return Balance(amount)
diff --git a/commune/modules/bittensor/utils/codes.py b/commune/modules/bittensor/utils/codes.py
deleted file mode 100644
index 874c4be93..000000000
--- a/commune/modules/bittensor/utils/codes.py
+++ /dev/null
@@ -1,144 +0,0 @@
-""" utils for rpc log, convert return code to string with color for the log
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-from loguru import logger
-import bittensor
-
-logger = logger.opt(colors=True)
-
-def code_to_string( code: 'bittensor.proto.ReturnCode' ) -> str:
- """ Return code -> string
- """
- if code == 0:
- return 'NoReturn'
- elif code == 1:
- return 'Success'
- elif code == 2:
- return 'Timeout'
- elif code == 3:
- return 'Backoff'
- elif code == 4:
- return 'Unavailable'
- elif code == 5:
- return 'NotImplemented'
- elif code == 6:
- return 'EmptyRequest'
- elif code == 7:
- return 'EmptyResponse'
- elif code == 8:
- return 'InvalidResponse'
- elif code == 9:
- return 'InvalidRequest'
- elif code == 10:
- return 'RequestShapeException'
- elif code == 11:
- return 'ResponseShapeException'
- elif code == 12:
- return 'RequestSerializationException'
- elif code == 13:
- return 'ResponseSerializationException'
- elif code == 14:
- return 'RequestDeserializationException'
- elif code == 15:
- return 'ResponseDeserializationException'
- elif code == 16:
- return 'NotServingNucleus'
- elif code == 17:
- return 'NucleusTimeout'
- elif code == 18:
- return 'NucleusFull'
- elif code == 19:
- return 'RequestIncompatibleVersion'
- elif code == 20:
- return 'ResponseIncompatibleVersion'
- elif code == 21:
- return 'SenderUnknown'
- elif code == 22:
- return 'UnknownException'
- elif code == 23:
- return 'Unauthenticated'
- elif code == 24:
- return 'BadEndpoint'
- else:
- return 'UnknownCode'
-
-def code_to_loguru_color( code: 'bittensor.proto.ReturnCode' ) -> str:
- """ Return code -> loguru color
- """
- if code == 0:
- return 'red'
- elif code == 1:
- return 'green'
- elif code == 2:
- return 'yellow'
- elif code == 3:
- return 'yellow'
- elif code == 4:
- return 'red'
- elif code == 5:
- return 'red'
- elif code == 6:
- return 'red'
- elif code == 7:
- return 'red'
- elif code == 8:
- return 'red'
- elif code == 9:
- return 'red'
- elif code == 10:
- return 'red'
- elif code == 11:
- return 'red'
- elif code == 12:
- return 'red'
- elif code == 13:
- return 'red'
- elif code == 14:
- return 'red'
- elif code == 15:
- return 'red'
- elif code == 16:
- return 'red'
- elif code == 17:
- return 'yellow'
- elif code == 18:
- return 'yellow'
- elif code == 19:
- return 'red'
- elif code == 20:
- return 'red'
- elif code == 21:
- return 'red'
- elif code == 22:
- return 'red'
- else:
- return 'red'
-
-def code_to_synapse( code: 'bittensor.proto.Synapse.SynapseType'):
- """Return Code -> Synapse Type"""
- if code == 1:
- return 'text_last_hidden_state'
- elif code == 2:
- return 'text_causal_lm'
- elif code == 3:
- return 'text_seq_2_seq'
- elif code == 4:
- return 'text_causal_lm_next'
- else:
- return 'Null'
\ No newline at end of file
diff --git a/commune/modules/bittensor/utils/networking.py b/commune/modules/bittensor/utils/networking.py
deleted file mode 100644
index 43fe1c32d..000000000
--- a/commune/modules/bittensor/utils/networking.py
+++ /dev/null
@@ -1,219 +0,0 @@
-""" Utils for handling local network with ip and ports.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import os
-import urllib
-import json
-import miniupnpc
-import netaddr
-import requests
-
-from loguru import logger
-
-def int_to_ip(int_val: int) -> str:
- r""" Maps an integer to a unique ip-string
- Args:
- int_val (:type:`int128`, `required`):
- The integer representation of an ip. Must be in the range (0, 3.4028237e+38).
-
- Returns:
- str_val (:tyep:`str`, `required):
- The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
-
- Raises:
- netaddr.core.AddrFormatError (Exception):
- Raised when the passed int_vals is not a valid ip int value.
- """
- return str(netaddr.IPAddress(int_val))
-
-def ip_to_int(str_val: str) -> int:
- r""" Maps an ip-string to a unique integer.
- arg:
- str_val (:tyep:`str`, `required):
- The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
-
- Returns:
- int_val (:type:`int128`, `required`):
- The integer representation of an ip. Must be in the range (0, 3.4028237e+38).
-
- Raises:
- netaddr.core.AddrFormatError (Exception):
- Raised when the passed str_val is not a valid ip string value.
- """
- return int(netaddr.IPAddress(str_val))
-
-def ip_version(str_val: str) -> int:
- r""" Returns the ip version (IPV4 or IPV6).
- arg:
- str_val (:tyep:`str`, `required):
- The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
-
- Returns:
- int_val (:type:`int128`, `required`):
- The ip version (Either 4 or 6 for IPv4/IPv6)
-
- Raises:
- netaddr.core.AddrFormatError (Exception):
- Raised when the passed str_val is not a valid ip string value.
- """
- return int(netaddr.IPAddress(str_val).version)
-
-def ip__str__(ip_type:int, ip_str:str, port:int):
- """ Return a formatted ip string
- """
- return "/ipv%i/%s:%i" % (ip_type, ip_str, port)
-
-class ExternalIPNotFound(Exception):
- """ Raised if we cannot attain your external ip from CURL/URLLIB/IPIFY/AWS """
-
-def get_external_ip() -> str:
- r""" Checks CURL/URLLIB/IPIFY/AWS for your external ip.
- Returns:
- external_ip (:obj:`str` `required`):
- Your routers external facing ip as a string.
-
- Raises:
- ExternalIPNotFound (Exception):
- Raised if all external ip attempts fail.
- """
- # --- Try AWS
- try:
- external_ip = requests.get('https://checkip.amazonaws.com').text.strip()
- assert isinstance(ip_to_int(external_ip), int)
- return str(external_ip)
- except Exception:
- pass
-
- # --- Try ipconfig.
- try:
- process = os.popen('curl -s ifconfig.me')
- external_ip = process.readline()
- process.close()
- assert isinstance(ip_to_int(external_ip), int)
- return str(external_ip)
- except Exception:
- pass
-
- # --- Try ipinfo.
- try:
- process = os.popen('curl -s https://ipinfo.io')
- external_ip = json.loads(process.read())['ip']
- process.close()
- assert isinstance(ip_to_int(external_ip), int)
- return str(external_ip)
- except Exception:
- pass
-
- # --- Try myip.dnsomatic
- try:
- process = os.popen('curl -s myip.dnsomatic.com')
- external_ip = process.readline()
- process.close()
- assert isinstance(ip_to_int(external_ip), int)
- return str(external_ip)
- except Exception:
- pass
-
- # --- Try urllib ipv6
- try:
- external_ip = urllib.request.urlopen('https://ident.me').read().decode('utf8')
- assert isinstance(ip_to_int(external_ip), int)
- return str(external_ip)
- except Exception:
- pass
-
- # --- Try Wikipedia
- try:
- external_ip = requests.get('https://www.wikipedia.org').headers['X-Client-IP']
- assert isinstance(ip_to_int(external_ip), int)
- return str(external_ip)
- except Exception:
- pass
-
- raise ExternalIPNotFound
-
-
-class UPNPCException(Exception):
- """ Raised when trying to perform a port mapping on your router. """
-
-
-def upnpc_create_port_map(port: int):
- r""" Creates a upnpc port map on your router from passed external_port to local port.
-
- Args:
- port (int, `required`):
- The local machine port to map from your external port.
-
- Return:
- external_port (int, `required`):
- The external port mapped to the local port on your machine.
-
- Raises:
- UPNPCException (Exception):
- Raised if UPNPC port mapping fails, for instance, if upnpc is not enabled on your router.
- """
- try:
- upnp = miniupnpc.UPnP()
- upnp.discoverdelay = 200
- logger.debug('UPNPC: Using UPnP to open a port on your router ...')
- logger.debug('UPNPC: Discovering... delay={}ms', upnp.discoverdelay)
- ndevices = upnp.discover()
- upnp.selectigd()
- logger.debug('UPNPC: ' + str(ndevices) + ' device(s) detected')
-
- ip = upnp.lanaddr
- external_ip = upnp.externalipaddress()
-
- logger.debug('UPNPC: your local ip address: ' + str(ip))
- logger.debug('UPNPC: your external ip address: ' + str(external_ip))
- logger.debug('UPNPC: status = ' + str(upnp.statusinfo()) + " connection type = " + str(upnp.connectiontype()))
-
- # find a free port for the redirection
- external_port = port
- rc = upnp.getspecificportmapping(external_port, 'TCP')
- while rc != None and external_port < 65536:
- external_port += 1
- rc = upnp.getspecificportmapping(external_port, 'TCP')
- if rc != None:
- raise UPNPCException("UPNPC: No available external ports for port mapping.")
-
- logger.info('UPNPC: trying to redirect remote: {}:{} => local: {}:{} over TCP', external_ip, external_port, ip, port)
- upnp.addportmapping(external_port, 'TCP', ip, port, 'Bittensor: %u' % external_port, '')
- logger.info('UPNPC: Create Success')
-
- return external_port
-
- except Exception as e:
- raise UPNPCException(e) from e
-
-def get_formatted_ws_endpoint_url(endpoint_url: str) -> str:
- """
- Returns a formatted websocket endpoint url.
- Note: The port (or lack thereof) is left unchanged
- Args:
- endpoint_url (str, `required`):
- The endpoint url to format.
- Returns:
- formatted_endpoint_url (str, `required`):
- The formatted endpoint url. In the form of ws:// or wss://
- """
- if endpoint_url[0:6] != "wss://" and endpoint_url[0:5] != "ws://":
- endpoint_url = "ws://{}".format(endpoint_url)
-
- return endpoint_url
\ No newline at end of file
diff --git a/commune/modules/bittensor/utils/register_cuda.py b/commune/modules/bittensor/utils/register_cuda.py
deleted file mode 100644
index 086f1f363..000000000
--- a/commune/modules/bittensor/utils/register_cuda.py
+++ /dev/null
@@ -1,110 +0,0 @@
-import binascii
-import hashlib
-import math
-from typing import Tuple
-
-import numpy as np
-from Crypto.Hash import keccak
-
-from contextlib import redirect_stdout
-import io
-
-
-def solve_cuda(nonce_start: np.int64, update_interval: np.int64, TPB: int, block_bytes: bytes, bn: int, difficulty: int, limit: int, dev_id: int = 0) -> Tuple[np.int64, bytes]:
- """
- Solves the PoW problem using CUDA.
- Args:
- nonce_start: int64
- Starting nonce.
- update_interval: int64
- Number of nonces to solve before updating block information.
- TPB: int
- Threads per block.
- block_bytes: bytes
- Bytes of the block hash. 64 bytes.
- difficulty: int256
- Difficulty of the PoW problem.
- limit: int256
- Upper limit of the nonce.
- dev_id: int (default=0)
- The CUDA device ID
- Returns:
- Tuple[int64, bytes]
- Tuple of the nonce and the seal corresponding to the solution.
- Returns -1 for nonce if no solution is found.
- """
-
- try:
- import cubit
- except ImportError:
- raise ImportError("Please install cubit")
-
-
- upper = int(limit // difficulty)
-
- upper_bytes = upper.to_bytes(32, byteorder='little', signed=False)
-
- def seal_meets_difficulty( seal:bytes, difficulty:int ):
- seal_number = int.from_bytes(seal, "big")
- product = seal_number * difficulty
- limit = int(math.pow(2,256))- 1
-
- return product < limit
-
- def hex_bytes_to_u8_list( hex_bytes: bytes ):
- hex_chunks = [int(hex_bytes[i:i+2], 16) for i in range(0, len(hex_bytes), 2)]
- return hex_chunks
-
- def create_seal_hash( block_bytes:bytes, nonce:int ) -> bytes:
- nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little'))
- pre_seal = nonce_bytes + block_bytes
- seal_sh256 = hashlib.sha256( bytearray(hex_bytes_to_u8_list(pre_seal)) ).digest()
- kec = keccak.new(digest_bits=256)
- seal = kec.update( seal_sh256 ).digest()
- return seal
-
- # Call cython function
- # int blockSize, uint64 nonce_start, uint64 update_interval, const unsigned char[:] limit,
- # const unsigned char[:] block_bytes, int dev_id
- solution = cubit.solve_cuda(TPB, nonce_start, update_interval, upper_bytes, block_bytes, dev_id) # 0 is first GPU
- seal = None
- if solution != -1:
- seal = create_seal_hash(block_bytes, solution)
- if seal_meets_difficulty(seal, difficulty):
- return solution, seal
- else:
- return -1, b'\x00' * 32
-
- return solution, seal
-
-def reset_cuda():
- """
- Resets the CUDA environment.
- """
- try:
- import cubit
- except ImportError:
- raise ImportError("Please install cubit")
-
- cubit.reset_cuda()
-
-def log_cuda_errors() -> str:
- """
- Logs any CUDA errors.
- """
- try:
- import cubit
- except ImportError:
- raise ImportError("Please install cubit")
-
- f = io.StringIO()
- with redirect_stdout(f):
- cubit.log_cuda_errors()
-
- s = f.getvalue()
-
- return s
-
-
-
-
diff --git a/commune/modules/bittensor/utils/registration.py b/commune/modules/bittensor/utils/registration.py
deleted file mode 100644
index 559e3548d..000000000
--- a/commune/modules/bittensor/utils/registration.py
+++ /dev/null
@@ -1,903 +0,0 @@
-import binascii
-import hashlib
-import math
-import multiprocessing
-import os
-import random
-import time
-from dataclasses import dataclass
-from datetime import timedelta
-from queue import Empty, Full
-from typing import Any, Callable, Dict, List, Optional, Tuple, Union
-
-import backoff
-import bittensor
-import torch
-from Crypto.Hash import keccak
-from rich import console as rich_console
-from rich import status as rich_status
-
-from .register_cuda import solve_cuda
-
-
-class CUDAException(Exception):
- """An exception raised when an error occurs in the CUDA environment."""
- pass
-
-
-def hex_bytes_to_u8_list( hex_bytes: bytes ):
- hex_chunks = [int(hex_bytes[i:i+2], 16) for i in range(0, len(hex_bytes), 2)]
- return hex_chunks
-
-
-def u8_list_to_hex( values: list ):
- total = 0
- for val in reversed(values):
- total = (total << 8) + val
- return total
-
-
-def create_seal_hash( block_hash:bytes, nonce:int ) -> bytes:
- block_bytes = block_hash.encode('utf-8')[2:]
- nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little'))
- pre_seal = nonce_bytes + block_bytes
- seal_sh256 = hashlib.sha256( bytearray(hex_bytes_to_u8_list(pre_seal)) ).digest()
- kec = keccak.new(digest_bits=256)
- seal = kec.update( seal_sh256 ).digest()
- return seal
-
-
-def seal_meets_difficulty( seal:bytes, difficulty:int ):
- seal_number = int.from_bytes(seal, "big")
- product = seal_number * difficulty
- limit = int(math.pow(2,256))- 1
- if product > limit:
- return False
- else:
- return True
-
-
-def solve_for_difficulty( block_hash, difficulty ):
- meets = False
- nonce = -1
- while not meets:
- nonce += 1
- seal = create_seal_hash( block_hash, nonce )
- meets = seal_meets_difficulty( seal, difficulty )
- if nonce > 1:
- break
- return nonce, seal
-
-
-def get_human_readable(num, suffix="H"):
- for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
- if abs(num) < 1000.0:
- return f"{num:3.1f}{unit}{suffix}"
- num /= 1000.0
- return f"{num:.1f}Y{suffix}"
-
-
-def millify(n: int):
- millnames = ['',' K',' M',' B',' T']
- n = float(n)
- millidx = max(0,min(len(millnames)-1,
- int(math.floor(0 if n == 0 else math.log10(abs(n))/3))))
-
- return '{:.2f}{}'.format(n / 10**(3 * millidx), millnames[millidx])
-
-
-def POWNotStale(subtensor: 'bittensor.Subtensor', pow_result: Dict) -> bool:
- """Returns True if the POW is not stale.
- This means the block the POW is solved for is within 3 blocks of the current block.
- """
- return pow_result['block_number'] >= subtensor.get_current_block() - 3
-
-
-@dataclass
-class POWSolution:
- """A solution to the registration PoW problem."""
- nonce: int
- block_number: int
- difficulty: int
- seal: bytes
-
-
-class SolverBase(multiprocessing.Process):
- """
- A process that solves the registration PoW problem.
-
- Args:
- proc_num: int
- The number of the process being created.
- num_proc: int
- The total number of processes running.
- update_interval: int
- The number of nonces to try to solve before checking for a new block.
- finished_queue: multiprocessing.Queue
- The queue to put the process number when a process finishes each update_interval.
- Used for calculating the average time per update_interval across all processes.
- solution_queue: multiprocessing.Queue
- The queue to put the solution the process has found during the pow solve.
- newBlockEvent: multiprocessing.Event
- The event to set by the main process when a new block is finalized in the network.
- The solver process will check for the event after each update_interval.
- The solver process will get the new block hash and difficulty and start solving for a new nonce.
- stopEvent: multiprocessing.Event
- The event to set by the main process when all the solver processes should stop.
- The solver process will check for the event after each update_interval.
- The solver process will stop when the event is set.
- Used to stop the solver processes when a solution is found.
- curr_block: multiprocessing.Array
- The array containing this process's current block hash.
- The main process will set the array to the new block hash when a new block is finalized in the network.
- The solver process will get the new block hash from this array when newBlockEvent is set.
- curr_block_num: multiprocessing.Value
- The value containing this process's current block number.
- The main process will set the value to the new block number when a new block is finalized in the network.
- The solver process will get the new block number from this value when newBlockEvent is set.
- curr_diff: multiprocessing.Array
- The array containing this process's current difficulty.
- The main process will set the array to the new difficulty when a new block is finalized in the network.
- The solver process will get the new difficulty from this array when newBlockEvent is set.
- check_block: multiprocessing.Lock
- The lock to prevent this process from getting the new block data while the main process is updating the data.
- limit: int
- The limit of the pow solve for a valid solution.
- """
- proc_num: int
- num_proc: int
- update_interval: int
- finished_queue: multiprocessing.Queue
- solution_queue: multiprocessing.Queue
- newBlockEvent: multiprocessing.Event
- stopEvent: multiprocessing.Event
- curr_block: multiprocessing.Array
- curr_block_num: multiprocessing.Value
- curr_diff: multiprocessing.Array
- check_block: multiprocessing.Lock
- limit: int
-
- def __init__(self, proc_num, num_proc, update_interval, finished_queue, solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit):
- multiprocessing.Process.__init__(self, daemon=True)
- self.proc_num = proc_num
- self.num_proc = num_proc
- self.update_interval = update_interval
- self.finished_queue = finished_queue
- self.solution_queue = solution_queue
- self.newBlockEvent = multiprocessing.Event()
- self.newBlockEvent.clear()
- self.curr_block = curr_block
- self.curr_block_num = curr_block_num
- self.curr_diff = curr_diff
- self.check_block = check_block
- self.stopEvent = stopEvent
- self.limit = limit
-
- def run(self):
- raise NotImplementedError("SolverBase is an abstract class")
-
-
-class Solver(SolverBase):
- def run(self):
- block_number: int
- block_bytes: bytes
- block_difficulty: int
- nonce_limit = int(math.pow(2,64)) - 1
-
- # Start at random nonce
- nonce_start = random.randint( 0, nonce_limit )
- nonce_end = nonce_start + self.update_interval
- while not self.stopEvent.is_set():
- if self.newBlockEvent.is_set():
- with self.check_block:
- block_number = self.curr_block_num.value
- block_bytes = bytes(self.curr_block)
- block_difficulty = registration_diff_unpack(self.curr_diff)
-
- self.newBlockEvent.clear()
-
- # Do a block of nonces
- solution = solve_for_nonce_block(self, nonce_start, nonce_end, block_bytes, block_difficulty, self.limit, block_number)
- if solution is not None:
- self.solution_queue.put(solution)
-
- try:
- # Send time
- self.finished_queue.put_nowait(self.proc_num)
- except Full:
- pass
-
- nonce_start = random.randint( 0, nonce_limit )
- nonce_start = nonce_start % nonce_limit
- nonce_end = nonce_start + self.update_interval
-
-
-class CUDASolver(SolverBase):
- dev_id: int
- TPB: int
-
- def __init__(self, proc_num, num_proc, update_interval, finished_queue, solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit, dev_id: int, TPB: int):
- super().__init__(proc_num, num_proc, update_interval, finished_queue, solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit)
- self.dev_id = dev_id
- self.TPB = TPB
-
- def run(self):
- block_number: int = 0 # dummy value
- block_bytes: bytes = b'0' * 32 # dummy value
- block_difficulty: int = int(math.pow(2,64)) - 1 # dummy value
- nonce_limit = int(math.pow(2,64)) - 1 # U64MAX
-
- # Start at random nonce
- nonce_start = random.randint( 0, nonce_limit )
- while not self.stopEvent.is_set():
- if self.newBlockEvent.is_set():
- with self.check_block:
- block_number = self.curr_block_num.value
- block_bytes = bytes(self.curr_block)
- block_difficulty = registration_diff_unpack(self.curr_diff)
-
- self.newBlockEvent.clear()
-
- # Do a block of nonces
- solution = solve_for_nonce_block_cuda(self, nonce_start, self.update_interval, block_bytes, block_difficulty, self.limit, block_number, self.dev_id, self.TPB)
- if solution is not None:
- self.solution_queue.put(solution)
-
- try:
- # Signal that a nonce_block was finished using queue
- # send our proc_num
- self.finished_queue.put(self.proc_num)
- except Full:
- pass
-
- # increase nonce by number of nonces processed
- nonce_start += self.update_interval * self.TPB
- nonce_start = nonce_start % nonce_limit
-
-
-def solve_for_nonce_block_cuda(solver: CUDASolver, nonce_start: int, update_interval: int, block_bytes: bytes, difficulty: int, limit: int, block_number: int, dev_id: int, TPB: int) -> Optional[POWSolution]:
- """Tries to solve the POW on a CUDA device for a block of nonces (nonce_start, nonce_start + update_interval * TPB"""
- solution, seal = solve_cuda(nonce_start,
- update_interval,
- TPB,
- block_bytes,
- block_number,
- difficulty,
- limit,
- dev_id)
-
- if (solution != -1):
- # Check if solution is valid (i.e. not -1)
- return POWSolution(solution, block_number, difficulty, seal)
-
- return None
-
-
-def solve_for_nonce_block(solver: Solver, nonce_start: int, nonce_end: int, block_bytes: bytes, difficulty: int, limit: int, block_number: int) -> Optional[POWSolution]:
- """Tries to solve the POW for a block of nonces (nonce_start, nonce_end)"""
- for nonce in range(nonce_start, nonce_end):
- # Create seal.
- nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little'))
- pre_seal = nonce_bytes + block_bytes
- seal_sh256 = hashlib.sha256( bytearray(hex_bytes_to_u8_list(pre_seal)) ).digest()
- kec = keccak.new(digest_bits=256)
- seal = kec.update( seal_sh256 ).digest()
- seal_number = int.from_bytes(seal, "big")
-
- # Check if seal meets difficulty
- product = seal_number * difficulty
- if product < limit:
- # Found a solution, save it.
- return POWSolution(nonce, block_number, difficulty, seal)
-
- return None
-
-
-def registration_diff_unpack(packed_diff: multiprocessing.Array) -> int:
- """Unpacks the packed two 32-bit integers into one 64-bit integer. Little endian."""
- return int(packed_diff[0] << 32 | packed_diff[1])
-
-
-def registration_diff_pack(diff: int, packed_diff: multiprocessing.Array):
- """Packs the difficulty into two 32-bit integers. Little endian."""
- packed_diff[0] = diff >> 32
- packed_diff[1] = diff & 0xFFFFFFFF # low 32 bits
-
-
-def update_curr_block(curr_diff: multiprocessing.Array, curr_block: multiprocessing.Array, curr_block_num: multiprocessing.Value, block_number: int, block_bytes: bytes, diff: int, lock: multiprocessing.Lock):
- with lock:
- curr_block_num.value = block_number
- for i in range(64):
- curr_block[i] = block_bytes[i]
- registration_diff_pack(diff, curr_diff)
-
-
-def get_cpu_count():
- try:
- return len(os.sched_getaffinity(0))
- except AttributeError:
- # OSX does not have sched_getaffinity
- return os.cpu_count()
-
-@dataclass
-class RegistrationStatistics:
- """Statistics for a registration."""
- time_spent_total: float
- rounds_total: int
- time_average: float
- time_spent: float
- hash_rate_perpetual: float
- hash_rate: float
- difficulty: int
- block_number: int
- block_hash: bytes
-
-
-class RegistrationStatisticsLogger:
- """Logs statistics for a registration."""
- console: rich_console.Console
- status: Optional[rich_status.Status]
-
- def __init__( self, console: rich_console.Console, output_in_place: bool = True) -> None:
- self.console = console
-
- if output_in_place:
- self.status = self.console.status("Solving")
- else:
- self.status = None
-
- def start( self ) -> None:
- if self.status is not None:
- self.status.start()
-
- def stop( self ) -> None:
- if self.status is not None:
- self.status.stop()
-
-
- def get_status_message(cls, stats: RegistrationStatistics, verbose: bool = False) -> str:
- message = \
- "Solving\n" + \
- f"Time Spent (total): [bold white]{timedelta(seconds=stats.time_spent_total)}[/bold white]\n" + \
- (
- f"Time Spent This Round: {timedelta(seconds=stats.time_spent)}\n" + \
- f"Time Spent Average: {timedelta(seconds=stats.time_average)}\n" if verbose else ""
- ) + \
- f"Registration Difficulty: [bold white]{millify(stats.difficulty)}[/bold white]\n" + \
- f"Iters (Its/Perp): [bold white]{get_human_readable(stats.hash_rate, 'H')}/s / " + \
- f"{get_human_readable(stats.hash_rate_perpetual, 'H')}/s[/bold white]\n" + \
- f"Block Number: [bold white]{stats.block_number}[/bold white]\n" + \
- f"Block Hash: [bold white]{stats.block_hash.encode('utf-8')}[/bold white]\n"
- return message
-
-
- def update( self, stats: RegistrationStatistics, verbose: bool = False ) -> None:
- if self.status is not None:
- self.status.update( self.get_status_message(stats, verbose=verbose) )
- else:
- self.console.log( self.get_status_message(stats, verbose=verbose), )
-
-
-def solve_for_difficulty_fast( subtensor, wallet, netuid: int, output_in_place: bool = True, num_processes: Optional[int] = None, update_interval: Optional[int] = None, n_samples: int = 10, alpha_: float = 0.80, log_verbose: bool = False ) -> Optional[POWSolution]:
- """
- Solves the POW for registration using multiprocessing.
- Args:
- subtensor
- Subtensor to connect to for block information and to submit.
- wallet:
- Wallet to use for registration.
- netuid: int
- The netuid of the subnet to register to.
- output_in_place: bool
- If true, prints the status in place. Otherwise, prints the status on a new line.
- num_processes: int
- Number of processes to use.
- update_interval: int
- Number of nonces to solve before updating block information.
- n_samples: int
- The number of samples of the hash_rate to keep for the EWMA
- alpha_: float
- The alpha for the EWMA for the hash_rate calculation
- log_verbose: bool
- If true, prints more verbose logging of the registration metrics.
- Note: The hash rate is calculated as an exponentially weighted moving average in order to make the measure more robust.
- Note:
- - We can also modify the update interval to do smaller blocks of work,
- while still updating the block information after a different number of nonces,
- to increase the transparency of the process while still keeping the speed.
- """
- if num_processes == None:
- # get the number of allowed processes for this process
- num_processes = min(1, get_cpu_count())
-
- if update_interval is None:
- update_interval = 50_000
-
- limit = int(math.pow(2,256)) - 1
-
- curr_block = multiprocessing.Array('h', 64, lock=True) # byte array
- curr_block_num = multiprocessing.Value('i', 0, lock=True) # int
- curr_diff = multiprocessing.Array('Q', [0, 0], lock=True) # [high, low]
-
- # Establish communication queues
- ## See the Solver class for more information on the queues.
- stopEvent = multiprocessing.Event()
- stopEvent.clear()
-
- solution_queue = multiprocessing.Queue()
- finished_queues = [multiprocessing.Queue() for _ in range(num_processes)]
- check_block = multiprocessing.Lock()
-
- # Start consumers
- solvers = [ Solver(i, num_processes, update_interval, finished_queues[i], solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit)
- for i in range(num_processes) ]
-
- # Get first block
- block_number, difficulty, block_hash = get_block_with_retry(subtensor = subtensor, netuid = netuid)
-
- block_bytes = block_hash.encode('utf-8')[2:]
- old_block_number = block_number
- # Set to current block
- update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, difficulty, check_block)
-
- # Set new block events for each solver to start at the initial block
- for worker in solvers:
- worker.newBlockEvent.set()
-
- for worker in solvers:
- worker.start() # start the solver processes
-
- start_time = time.time() # time that the registration started
- time_last = start_time # time that the last work blocks completed
-
- curr_stats = RegistrationStatistics(
- time_spent_total = 0.0,
- time_average = 0.0,
- rounds_total = 0,
- time_spent = 0.0,
- hash_rate_perpetual = 0.0,
- hash_rate = 0.0,
- difficulty = difficulty,
- block_number = block_number,
- block_hash = block_hash
- )
-
- start_time_perpetual = time.time()
-
-
- console = bittensor.__console__
- logger = RegistrationStatisticsLogger(console, output_in_place)
- logger.start()
-
- solution = None
-
- hash_rates = [0] * n_samples # The last n true hash_rates
- weights = [alpha_ ** i for i in range(n_samples)] # weights decay by alpha
-
- while not wallet.is_registered(netuid = netuid, subtensor = subtensor):
- # Wait until a solver finds a solution
- try:
- solution = solution_queue.get(block=True, timeout=0.25)
- if solution is not None:
- break
- except Empty:
- # No solution found, try again
- pass
-
- # check for new block
- old_block_number = check_for_newest_block_and_update(
- subtensor = subtensor,
- netuid = netuid,
- old_block_number=old_block_number,
- curr_diff=curr_diff,
- curr_block=curr_block,
- curr_block_num=curr_block_num,
- curr_stats=curr_stats,
- update_curr_block=update_curr_block,
- check_block=check_block,
- solvers=solvers
- )
-
- num_time = 0
- for finished_queue in finished_queues:
- try:
- proc_num = finished_queue.get(timeout=0.1)
- num_time += 1
-
- except Empty:
- continue
-
- time_now = time.time() # get current time
- time_since_last = time_now - time_last # get time since last work block(s)
- if num_time > 0 and time_since_last > 0.0:
- # create EWMA of the hash_rate to make measure more robust
-
- hash_rate_ = (num_time * update_interval) / time_since_last
- hash_rates.append(hash_rate_)
- hash_rates.pop(0) # remove the 0th data point
- curr_stats.hash_rate = sum([hash_rates[i]*weights[i] for i in range(n_samples)])/(sum(weights))
-
- # update time last to now
- time_last = time_now
-
- curr_stats.time_average = (curr_stats.time_average*curr_stats.rounds_total + curr_stats.time_spent)/(curr_stats.rounds_total+num_time)
- curr_stats.rounds_total += num_time
-
- # Update stats
- curr_stats.time_spent = time_since_last
- new_time_spent_total = time_now - start_time_perpetual
- curr_stats.hash_rate_perpetual = (curr_stats.rounds_total*update_interval)/ new_time_spent_total
- curr_stats.time_spent_total = new_time_spent_total
-
- # Update the logger
- logger.update(curr_stats, verbose=log_verbose)
-
- # exited while, solution contains the nonce or wallet is registered
- stopEvent.set() # stop all other processes
- logger.stop()
-
- # terminate and wait for all solvers to exit
- terminate_workers_and_wait_for_exit(solvers)
-
- return solution
-
-
-@backoff.on_exception(backoff.constant,
- Exception,
- interval=1,
- max_tries=3)
-def get_block_with_retry(subtensor: 'bittensor.Subtensor', netuid: int) -> Tuple[int, int, bytes]:
- """
- Gets the current block number, difficulty, and block hash from the substrate node.
-
- Args:
- subtensor (:obj:`bittensor.Subtensor`, `required`):
- The subtensor object to use to get the block number, difficulty, and block hash.
-
- netuid (:obj:`int`, `required`):
- The netuid of the network to get the block number, difficulty, and block hash from.
-
- Returns:
- block_number (:obj:`int`):
- The current block number.
-
- difficulty (:obj:`int`):
- The current difficulty of the subnet.
-
- block_hash (:obj:`bytes`):
- The current block hash.
-
- Raises:
- Exception: If the block hash is None.
- ValueError: If the difficulty is None.
- """
- block_number = subtensor.get_current_block()
- difficulty = subtensor.difficulty(netuid = netuid)
- block_hash = subtensor.substrate.get_block_hash( block_number )
- if block_hash is None:
- raise Exception("Network error. Could not connect to substrate to get block hash")
- if difficulty is None:
- raise ValueError("Chain error. Difficulty is None")
- return block_number, difficulty, block_hash
-
-
-class UsingSpawnStartMethod():
- def __init__(self, force: bool = False):
- self._old_start_method = None
- self._force = force
-
- def __enter__(self):
- self._old_start_method = multiprocessing.get_start_method(allow_none=True)
- if self._old_start_method == None:
- self._old_start_method = 'spawn' # default to spawn
-
- multiprocessing.set_start_method('spawn', force=self._force)
-
- def __exit__(self, *args):
- # restore the old start method
- multiprocessing.set_start_method(self._old_start_method, force=True)
-
-
-def check_for_newest_block_and_update(
- subtensor: 'bittensor.Subtensor',
- netuid: int,
- old_block_number: int,
- curr_diff: multiprocessing.Array,
- curr_block: multiprocessing.Array,
- curr_block_num: multiprocessing.Value,
- update_curr_block: Callable,
- check_block: 'multiprocessing.Lock',
- solvers: List[Solver],
- curr_stats: RegistrationStatistics
- ) -> int:
- """
- Checks for a new block and updates the current block information if a new block is found.
-
- Args:
- subtensor (:obj:`bittensor.Subtensor`, `required`):
- The subtensor object to use for getting the current block.
- netuid (:obj:`int`, `required`):
- The netuid to use for retrieving the difficulty.
- old_block_number (:obj:`int`, `required`):
- The old block number to check against.
- curr_diff (:obj:`multiprocessing.Array`, `required`):
- The current difficulty as a multiprocessing array.
- curr_block (:obj:`multiprocessing.Array`, `required`):
- Where the current block is stored as a multiprocessing array.
- curr_block_num (:obj:`multiprocessing.Value`, `required`):
- Where the current block number is stored as a multiprocessing value.
- update_curr_block (:obj:`Callable`, `required`):
- A function that updates the current block.
- check_block (:obj:`multiprocessing.Lock`, `required`):
- A mp lock that is used to check for a new block.
- solvers (:obj:`List[Solver]`, `required`):
- A list of solvers to update the current block for.
- curr_stats (:obj:`RegistrationStatistics`, `required`):
- The current registration statistics to update.
-
- Returns:
- (int) The current block number.
- """
- block_number = subtensor.get_current_block()
- if block_number != old_block_number:
- old_block_number = block_number
- # update block information
- block_number, difficulty, block_hash = get_block_with_retry(subtensor = subtensor, netuid = netuid)
- block_bytes = block_hash.encode('utf-8')[2:]
-
- update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, difficulty, check_block)
- # Set new block events for each solver
-
- for worker in solvers:
- worker.newBlockEvent.set()
-
- # update stats
- curr_stats.block_number = block_number
- curr_stats.block_hash = block_hash
- curr_stats.difficulty = difficulty
-
- return old_block_number
-
-
-def solve_for_difficulty_fast_cuda( subtensor: 'bittensor.Subtensor', wallet: 'bittensor.Wallet', netuid: int, output_in_place: bool = True, update_interval: int = 50_000, TPB: int = 512, dev_id: Union[List[int], int] = 0, n_samples: int = 10, alpha_: float = 0.80, log_verbose: bool = False ) -> Optional[POWSolution]:
- """
- Solves the registration fast using CUDA
- Args:
- subtensor: bittensor.Subtensor
- The subtensor node to grab blocks
- wallet: bittensor.Wallet
- The wallet to register
- netuid: int
- The netuid of the subnet to register to.
- output_in_place: bool
- If true, prints the output in place, otherwise prints to new lines
- update_interval: int
- The number of nonces to try before checking for more blocks
- TPB: int
- The number of threads per block. CUDA param that should match the GPU capability
- dev_id: Union[List[int], int]
- The CUDA device IDs to execute the registration on, either a single device or a list of devices
- n_samples: int
- The number of samples of the hash_rate to keep for the EWMA
- alpha_: float
- The alpha for the EWMA for the hash_rate calculation
- log_verbose: bool
- If true, prints more verbose logging of the registration metrics.
- Note: The hash rate is calculated as an exponentially weighted moving average in order to make the measure more robust.
- """
- if isinstance(dev_id, int):
- dev_id = [dev_id]
- elif dev_id is None:
- dev_id = [0]
-
- if update_interval is None:
- update_interval = 50_000
-
- if not torch.cuda.is_available():
- raise Exception("CUDA not available")
-
- limit = int(math.pow(2,256)) - 1
-
- # Set mp start to use spawn so CUDA doesn't complain
- with UsingSpawnStartMethod(force=True):
- curr_block = multiprocessing.Array('h', 64, lock=True) # byte array
- curr_block_num = multiprocessing.Value('i', 0, lock=True) # int
- curr_diff = multiprocessing.Array('Q', [0, 0], lock=True) # [high, low]
-
- ## Create a worker per CUDA device
- num_processes = len(dev_id)
-
- # Establish communication queues
- stopEvent = multiprocessing.Event()
- stopEvent.clear()
- solution_queue = multiprocessing.Queue()
- finished_queues = [multiprocessing.Queue() for _ in range(num_processes)]
- check_block = multiprocessing.Lock()
-
- # Start workers
- solvers = [ CUDASolver(i, num_processes, update_interval, finished_queues[i], solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit, dev_id[i], TPB)
- for i in range(num_processes) ]
-
-
- # Get first block
- block_number, difficulty, block_hash = get_block_with_retry(subtensor = subtensor, netuid = netuid)
-
- block_bytes = block_hash.encode('utf-8')[2:]
- old_block_number = block_number
-
- # Set to current block
- update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, difficulty, check_block)
-
- # Set new block events for each solver to start at the initial block
- for worker in solvers:
- worker.newBlockEvent.set()
-
- for worker in solvers:
- worker.start() # start the solver processes
-
- start_time = time.time() # time that the registration started
- time_last = start_time # time that the last work blocks completed
-
- curr_stats = RegistrationStatistics(
- time_spent_total = 0.0,
- time_average = 0.0,
- rounds_total = 0,
- time_spent = 0.0,
- hash_rate_perpetual = 0.0,
- hash_rate = 0.0, # EWMA hash_rate (H/s)
- difficulty = difficulty,
- block_number = block_number,
- block_hash = block_hash
- )
-
- start_time_perpetual = time.time()
-
- console = bittensor.__console__
- logger = RegistrationStatisticsLogger(console, output_in_place)
- logger.start()
-
- hash_rates = [0] * n_samples # The last n true hash_rates
- weights = [alpha_ ** i for i in range(n_samples)] # weights decay by alpha
-
- solution = None
- while not wallet.is_registered(netuid = netuid, subtensor = subtensor):
- # Wait until a solver finds a solution
- try:
- solution = solution_queue.get(block=True, timeout=0.15)
- if solution is not None:
- break
- except Empty:
- # No solution found, try again
- pass
-
- # check for new block
- old_block_number = check_for_newest_block_and_update(
- subtensor = subtensor,
- netuid = netuid,
- curr_diff=curr_diff,
- curr_block=curr_block,
- curr_block_num=curr_block_num,
- old_block_number=old_block_number,
- curr_stats=curr_stats,
- update_curr_block=update_curr_block,
- check_block=check_block,
- solvers=solvers
- )
-
- num_time = 0
- # Get times for each solver
- for finished_queue in finished_queues:
- try:
- proc_num = finished_queue.get(timeout=0.1)
- num_time += 1
-
- except Empty:
- continue
-
- time_now = time.time() # get current time
- time_since_last = time_now - time_last # get time since last work block(s)
- if num_time > 0 and time_since_last > 0.0:
- # create EWMA of the hash_rate to make measure more robust
-
- hash_rate_ = (num_time * TPB * update_interval) / time_since_last
- hash_rates.append(hash_rate_)
- hash_rates.pop(0) # remove the 0th data point
- curr_stats.hash_rate = sum([hash_rates[i]*weights[i] for i in range(n_samples)])/(sum(weights))
-
- # update time last to now
- time_last = time_now
-
- curr_stats.time_average = (curr_stats.time_average*curr_stats.rounds_total + curr_stats.time_spent)/(curr_stats.rounds_total+num_time)
- curr_stats.rounds_total += num_time
-
- # Update stats
- curr_stats.time_spent = time_since_last
- new_time_spent_total = time_now - start_time_perpetual
- curr_stats.hash_rate_perpetual = (curr_stats.rounds_total * (TPB * update_interval))/ new_time_spent_total
- curr_stats.time_spent_total = new_time_spent_total
-
- # Update the logger
- logger.update(curr_stats, verbose=log_verbose)
-
- # exited while, found_solution contains the nonce or wallet is registered
-
- stopEvent.set() # stop all other processes
- logger.stop()
-
- # terminate and wait for all solvers to exit
- terminate_workers_and_wait_for_exit(solvers)
-
- return solution
-
-
-def terminate_workers_and_wait_for_exit(workers: List[multiprocessing.Process]) -> None:
- for worker in workers:
- worker.terminate()
- worker.join()
-
-
-def create_pow(
- subtensor,
- wallet,
- netuid: int,
- output_in_place: bool = True,
- cuda: bool = False,
- dev_id: Union[List[int], int] = 0,
- tpb: int = 256,
- num_processes: int = None,
- update_interval: int = None,
- log_verbose: bool = False
- ) -> Optional[Dict[str, Any]]:
- """
- Creates a proof of work for the given subtensor and wallet.
- Args:
- subtensor (:obj:`bittensor.subtensor.Subtensor`, `required`):
- The subtensor to create a proof of work for.
- wallet (:obj:`bittensor.wallet.Wallet`, `required`):
- The wallet to create a proof of work for.
- netuid (:obj:`int`, `required`):
- The netuid for the subnet to create a proof of work for.
- output_in_place (:obj:`bool`, `optional`, defaults to :obj:`True`):
- If true, prints the progress of the proof of work to the console
- in-place. Meaning the progress is printed on the same lines.
- cuda (:obj:`bool`, `optional`, defaults to :obj:`False`):
- If true, uses CUDA to solve the proof of work.
- dev_id (:obj:`Union[List[int], int]`, `optional`, defaults to :obj:`0`):
- The CUDA device id(s) to use. If cuda is true and dev_id is a list,
- then multiple CUDA devices will be used to solve the proof of work.
- tpb (:obj:`int`, `optional`, defaults to :obj:`256`):
- The number of threads per block to use when solving the proof of work.
- Should be a multiple of 32.
- num_processes (:obj:`int`, `optional`, defaults to :obj:`None`):
- The number of processes to use when solving the proof of work.
- If None, then the number of processes is equal to the number of
- CPU cores.
- update_interval (:obj:`int`, `optional`, defaults to :obj:`None`):
- The number of nonces to run before checking for a new block.
- log_verbose (:obj:`bool`, `optional`, defaults to :obj:`False`):
- If true, prints the progress of the proof of work more verbosely.
- Returns:
- :obj:`Optional[Dict[str, Any]]`: The proof of work solution or None if
- the wallet is already registered or there is a different error.
-
- Raises:
- :obj:`ValueError`: If the subnet does not exist.
- """
- if not subtensor.subnet_exists(netuid = netuid):
- raise ValueError(f'Subnet {netuid} does not exist')
-
- if cuda:
- solution: POWSolution = solve_for_difficulty_fast_cuda( subtensor, wallet, netuid = netuid, output_in_place=output_in_place, \
- dev_id=dev_id, TPB=tpb, update_interval=update_interval, log_verbose=log_verbose
- )
- else:
- solution: POWSolution = solve_for_difficulty_fast( subtensor, wallet, netuid = netuid, output_in_place=output_in_place, \
- num_processes=num_processes, update_interval=update_interval, log_verbose=log_verbose
- )
-
- return None if solution is None else {
- 'nonce': solution.nonce,
- 'difficulty': solution.difficulty,
- 'block_number': solution.block_number,
- 'work': binascii.hexlify(solution.seal)
- }
diff --git a/commune/modules/bittensor/utils/registratrion_old.py b/commune/modules/bittensor/utils/registratrion_old.py
deleted file mode 100644
index ecf42e45a..000000000
--- a/commune/modules/bittensor/utils/registratrion_old.py
+++ /dev/null
@@ -1,835 +0,0 @@
-import binascii
-import hashlib
-import math
-import multiprocessing
-import os
-import random
-import time
-from dataclasses import dataclass
-from datetime import timedelta
-from queue import Empty, Full
-from typing import Any, Callable, Dict, List, Optional, Tuple, Union
-
-import backoff
-import bittensor
-import torch
-from Crypto.Hash import keccak
-from rich import console as rich_console
-from rich import status as rich_status
-
-from .register_cuda import solve_cuda
-
-
-class CUDAException(Exception):
- """An exception raised when an error occurs in the CUDA environment."""
- pass
-
-
-def hex_bytes_to_u8_list( hex_bytes: bytes ):
- hex_chunks = [int(hex_bytes[i:i+2], 16) for i in range(0, len(hex_bytes), 2)]
- return hex_chunks
-
-
-def u8_list_to_hex( values: list ):
- total = 0
- for val in reversed(values):
- total = (total << 8) + val
- return total
-
-
-def create_seal_hash( block_hash:bytes, nonce:int ) -> bytes:
- block_bytes = block_hash.encode('utf-8')[2:]
- nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little'))
- pre_seal = nonce_bytes + block_bytes
- seal_sh256 = hashlib.sha256( bytearray(hex_bytes_to_u8_list(pre_seal)) ).digest()
- kec = keccak.new(digest_bits=256)
- seal = kec.update( seal_sh256 ).digest()
- return seal
-
-
-def seal_meets_difficulty( seal:bytes, difficulty:int ):
- seal_number = int.from_bytes(seal, "big")
- product = seal_number * difficulty
- limit = int(math.pow(2,256))- 1
- if product > limit:
- return False
- else:
- return True
-
-
-def solve_for_difficulty( block_hash, difficulty ):
- meets = False
- nonce = -1
- while not meets:
- nonce += 1
- seal = create_seal_hash( block_hash, nonce )
- meets = seal_meets_difficulty( seal, difficulty )
- if nonce > 1:
- break
- return nonce, seal
-
-
-def get_human_readable(num, suffix="H"):
- for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
- if abs(num) < 1000.0:
- return f"{num:3.1f}{unit}{suffix}"
- num /= 1000.0
- return f"{num:.1f}Y{suffix}"
-
-
-def millify(n: int):
- millnames = ['',' K',' M',' B',' T']
- n = float(n)
- millidx = max(0,min(len(millnames)-1,
- int(math.floor(0 if n == 0 else math.log10(abs(n))/3))))
-
- return '{:.2f}{}'.format(n / 10**(3 * millidx), millnames[millidx])
-
-
-def POWNotStale(subtensor: 'bittensor.Subtensor', pow_result: Dict) -> bool:
- """Returns True if the POW is not stale.
- This means the block the POW is solved for is within 3 blocks of the current block.
- """
- return pow_result['block_number'] >= subtensor.get_current_block() - 3
-
-
-@dataclass
-class POWSolution:
- """A solution to the registration PoW problem."""
- nonce: int
- block_number: int
- difficulty: int
- seal: bytes
-
-
-class SolverBase(multiprocessing.Process):
- """
- A process that solves the registration PoW problem.
- Args:
- proc_num: int
- The number of the process being created.
- num_proc: int
- The total number of processes running.
- update_interval: int
- The number of nonces to try to solve before checking for a new block.
- finished_queue: multiprocessing.Queue
- The queue to put the process number when a process finishes each update_interval.
- Used for calculating the average time per update_interval across all processes.
- solution_queue: multiprocessing.Queue
- The queue to put the solution the process has found during the pow solve.
- newBlockEvent: multiprocessing.Event
- The event to set by the main process when a new block is finalized in the network.
- The solver process will check for the event after each update_interval.
- The solver process will get the new block hash and difficulty and start solving for a new nonce.
- stopEvent: multiprocessing.Event
- The event to set by the main process when all the solver processes should stop.
- The solver process will check for the event after each update_interval.
- The solver process will stop when the event is set.
- Used to stop the solver processes when a solution is found.
- curr_block: multiprocessing.Array
- The array containing this process's current block hash.
- The main process will set the array to the new block hash when a new block is finalized in the network.
- The solver process will get the new block hash from this array when newBlockEvent is set.
- curr_block_num: multiprocessing.Value
- The value containing this process's current block number.
- The main process will set the value to the new block number when a new block is finalized in the network.
- The solver process will get the new block number from this value when newBlockEvent is set.
- curr_diff: multiprocessing.Array
- The array containing this process's current difficulty.
- The main process will set the array to the new difficulty when a new block is finalized in the network.
- The solver process will get the new difficulty from this array when newBlockEvent is set.
- check_block: multiprocessing.Lock
- The lock to prevent this process from getting the new block data while the main process is updating the data.
- limit: int
- The limit of the pow solve for a valid solution.
- """
- proc_num: int
- num_proc: int
- update_interval: int
- finished_queue: multiprocessing.Queue
- solution_queue: multiprocessing.Queue
- newBlockEvent: multiprocessing.Event
- stopEvent: multiprocessing.Event
- curr_block: multiprocessing.Array
- curr_block_num: multiprocessing.Value
- curr_diff: multiprocessing.Array
- check_block: multiprocessing.Lock
- limit: int
-
- def __init__(self, proc_num, num_proc, update_interval, finished_queue, solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit):
- multiprocessing.Process.__init__(self, daemon=True)
- self.proc_num = proc_num
- self.num_proc = num_proc
- self.update_interval = update_interval
- self.finished_queue = finished_queue
- self.solution_queue = solution_queue
- self.newBlockEvent = multiprocessing.Event()
- self.newBlockEvent.clear()
- self.curr_block = curr_block
- self.curr_block_num = curr_block_num
- self.curr_diff = curr_diff
- self.check_block = check_block
- self.stopEvent = stopEvent
- self.limit = limit
-
- def run(self):
- raise NotImplementedError("SolverBase is an abstract class")
-
-
-class Solver(SolverBase):
- def run(self):
- block_number: int
- block_bytes: bytes
- block_difficulty: int
- nonce_limit = int(math.pow(2,64)) - 1
-
- # Start at random nonce
- nonce_start = random.randint( 0, nonce_limit )
- nonce_end = nonce_start + self.update_interval
- while not self.stopEvent.is_set():
- if self.newBlockEvent.is_set():
- with self.check_block:
- block_number = self.curr_block_num.value
- block_bytes = bytes(self.curr_block)
- block_difficulty = registration_diff_unpack(self.curr_diff)
-
- self.newBlockEvent.clear()
-
- # Do a block of nonces
- solution = solve_for_nonce_block(self, nonce_start, nonce_end, block_bytes, block_difficulty, self.limit, block_number)
- if solution is not None:
- self.solution_queue.put(solution)
-
- try:
- # Send time
- self.finished_queue.put_nowait(self.proc_num)
- except Full:
- pass
-
- nonce_start = random.randint( 0, nonce_limit )
- nonce_start = nonce_start % nonce_limit
- nonce_end = nonce_start + self.update_interval
-
-
-class CUDASolver(SolverBase):
- dev_id: int
- TPB: int
-
- def __init__(self, proc_num, num_proc, update_interval, finished_queue, solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit, dev_id: int, TPB: int):
- super().__init__(proc_num, num_proc, update_interval, finished_queue, solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit)
- self.dev_id = dev_id
- self.TPB = TPB
-
- def run(self):
- block_number: int = 0 # dummy value
- block_bytes: bytes = b'0' * 32 # dummy value
- block_difficulty: int = int(math.pow(2,64)) - 1 # dummy value
- nonce_limit = int(math.pow(2,64)) - 1 # U64MAX
-
- # Start at random nonce
- nonce_start = random.randint( 0, nonce_limit )
- while not self.stopEvent.is_set():
- if self.newBlockEvent.is_set():
- with self.check_block:
- block_number = self.curr_block_num.value
- block_bytes = bytes(self.curr_block)
- block_difficulty = registration_diff_unpack(self.curr_diff)
-
- self.newBlockEvent.clear()
-
- # Do a block of nonces
- solution = solve_for_nonce_block_cuda(self, nonce_start, self.update_interval, block_bytes, block_difficulty, self.limit, block_number, self.dev_id, self.TPB)
- if solution is not None:
- self.solution_queue.put(solution)
-
- try:
- # Signal that a nonce_block was finished using queue
- # send our proc_num
- self.finished_queue.put(self.proc_num)
- except Full:
- pass
-
- # increase nonce by number of nonces processed
- nonce_start += self.update_interval * self.TPB
- nonce_start = nonce_start % nonce_limit
-
-
-def solve_for_nonce_block_cuda(solver: CUDASolver, nonce_start: int, update_interval: int, block_bytes: bytes, difficulty: int, limit: int, block_number: int, dev_id: int, TPB: int) -> Optional[POWSolution]:
- """Tries to solve the POW on a CUDA device for a block of nonces (nonce_start, nonce_start + update_interval * TPB"""
- solution, seal = solve_cuda(nonce_start,
- update_interval,
- TPB,
- block_bytes,
- block_number,
- difficulty,
- limit,
- dev_id)
-
- if (solution != -1):
- # Check if solution is valid (i.e. not -1)
- return POWSolution(solution, block_number, difficulty, seal)
-
- return None
-
-
-def solve_for_nonce_block(solver: Solver, nonce_start: int, nonce_end: int, block_bytes: bytes, difficulty: int, limit: int, block_number: int) -> Optional[POWSolution]:
- """Tries to solve the POW for a block of nonces (nonce_start, nonce_end)"""
- for nonce in range(nonce_start, nonce_end):
- # Create seal.
- nonce_bytes = binascii.hexlify(nonce.to_bytes(8, 'little'))
- pre_seal = nonce_bytes + block_bytes
- seal_sh256 = hashlib.sha256( bytearray(hex_bytes_to_u8_list(pre_seal)) ).digest()
- kec = keccak.new(digest_bits=256)
- seal = kec.update( seal_sh256 ).digest()
- seal_number = int.from_bytes(seal, "big")
-
- # Check if seal meets difficulty
- product = seal_number * difficulty
- if product < limit:
- # Found a solution, save it.
- return POWSolution(nonce, block_number, difficulty, seal)
-
- return None
-
-
-def registration_diff_unpack(packed_diff: multiprocessing.Array) -> int:
- """Unpacks the packed two 32-bit integers into one 64-bit integer. Little endian."""
- return int(packed_diff[0] << 32 | packed_diff[1])
-
-
-def registration_diff_pack(diff: int, packed_diff: multiprocessing.Array):
- """Packs the difficulty into two 32-bit integers. Little endian."""
- packed_diff[0] = diff >> 32
- packed_diff[1] = diff & 0xFFFFFFFF # low 32 bits
-
-
-def update_curr_block(curr_diff: multiprocessing.Array, curr_block: multiprocessing.Array, curr_block_num: multiprocessing.Value, block_number: int, block_bytes: bytes, diff: int, lock: multiprocessing.Lock):
- with lock:
- curr_block_num.value = block_number
- for i in range(64):
- curr_block[i] = block_bytes[i]
- registration_diff_pack(diff, curr_diff)
-
-
-def get_cpu_count():
- try:
- return len(os.sched_getaffinity(0))
- except AttributeError:
- # OSX does not have sched_getaffinity
- return os.cpu_count()
-
-@dataclass
-class RegistrationStatistics:
- """Statistics for a registration."""
- time_spent_total: float
- rounds_total: int
- time_average: float
- time_spent: float
- hash_rate_perpetual: float
- hash_rate: float
- difficulty: int
- block_number: int
- block_hash: bytes
-
-
-class RegistrationStatisticsLogger:
- """Logs statistics for a registration."""
- console: rich_console.Console
- status: Optional[rich_status.Status]
-
- def __init__( self, console: rich_console.Console, output_in_place: bool = True) -> None:
- self.console = console
-
- if output_in_place:
- self.status = self.console.status("Solving")
- else:
- self.status = None
-
- def start( self ) -> None:
- if self.status is not None:
- self.status.start()
-
- def stop( self ) -> None:
- if self.status is not None:
- self.status.stop()
-
-
- def get_status_message(cls, stats: RegistrationStatistics, verbose: bool = False) -> str:
- message = \
- "Solving\n" + \
- f"Time Spent (total): [bold white]{timedelta(seconds=stats.time_spent_total)}[/bold white]\n" + \
- (
- f"Time Spent This Round: {timedelta(seconds=stats.time_spent)}\n" + \
- f"Time Spent Average: {timedelta(seconds=stats.time_average)}\n" if verbose else ""
- ) + \
- f"Registration Difficulty: [bold white]{millify(stats.difficulty)}[/bold white]\n" + \
- f"Iters (Inst/Perp): [bold white]{get_human_readable(stats.hash_rate, 'H')}/s / " + \
- f"{get_human_readable(stats.hash_rate_perpetual, 'H')}/s[/bold white]\n" + \
- f"Block Number: [bold white]{stats.block_number}[/bold white]\n" + \
- f"Block Hash: [bold white]{stats.block_hash.encode('utf-8')}[/bold white]\n"
- return message
-
-
- def update( self, stats: RegistrationStatistics, verbose: bool = False ) -> None:
- if self.status is not None:
- self.status.update( self.get_status_message(stats, verbose=verbose) )
- else:
- self.console.log( self.get_status_message(stats, verbose=verbose), )
-
-
-def solve_for_difficulty_fast( subtensor, wallet, output_in_place: bool = True, num_processes: Optional[int] = None, update_interval: Optional[int] = None, n_samples: int = 10, alpha_: float = 0.80, log_verbose: bool = False ) -> Optional[POWSolution]:
- """
- Solves the POW for registration using multiprocessing.
- Args:
- subtensor
- Subtensor to connect to for block information and to submit.
- wallet:
- Wallet to use for registration.
- output_in_place: bool
- If true, prints the status in place. Otherwise, prints the status on a new line.
- num_processes: int
- Number of processes to use.
- update_interval: int
- Number of nonces to solve before updating block information.
- n_samples: int
- The number of samples of the hash_rate to keep for the EWMA
- alpha_: float
- The alpha for the EWMA for the hash_rate calculation
- log_verbose: bool
- If true, prints more verbose logging of the registration metrics.
- Note: The hash rate is calculated as an exponentially weighted moving average in order to make the measure more robust.
- Note:
- - We can also modify the update interval to do smaller blocks of work,
- while still updating the block information after a different number of nonces,
- to increase the transparency of the process while still keeping the speed.
- """
- if num_processes == None:
- # get the number of allowed processes for this process
- num_processes = min(1, get_cpu_count())
-
- if update_interval is None:
- update_interval = 50_000
-
- limit = int(math.pow(2,256)) - 1
-
- curr_block = multiprocessing.Array('h', 64, lock=True) # byte array
- curr_block_num = multiprocessing.Value('i', 0, lock=True) # int
- curr_diff = multiprocessing.Array('Q', [0, 0], lock=True) # [high, low]
-
- # Establish communication queues
- ## See the Solver class for more information on the queues.
- stopEvent = multiprocessing.Event()
- stopEvent.clear()
-
- solution_queue = multiprocessing.Queue()
- finished_queues = [multiprocessing.Queue() for _ in range(num_processes)]
- check_block = multiprocessing.Lock()
-
- # Start consumers
- solvers = [ Solver(i, num_processes, update_interval, finished_queues[i], solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit)
- for i in range(num_processes) ]
-
- # Get first block
- block_number = subtensor.get_current_block()
- difficulty = subtensor.difficulty
- block_hash = subtensor.substrate.get_block_hash( block_number )
- while block_hash == None:
- block_hash = subtensor.substrate.get_block_hash( block_number )
- block_bytes = block_hash.encode('utf-8')[2:]
- old_block_number = block_number
- # Set to current block
- update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, difficulty, check_block)
-
- # Set new block events for each solver to start at the initial block
- for worker in solvers:
- worker.newBlockEvent.set()
-
- for worker in solvers:
- worker.start() # start the solver processes
-
- start_time = time.time() # time that the registration started
- time_last = start_time # time that the last work blocks completed
-
- curr_stats = RegistrationStatistics(
- time_spent_total = 0.0,
- time_average = 0.0,
- rounds_total = 0,
- time_spent = 0.0,
- hash_rate_perpetual = 0.0,
- hash_rate = 0.0,
- difficulty = difficulty,
- block_number = block_number,
- block_hash = block_hash
- )
-
- start_time_perpetual = time.time()
-
-
- console = bittensor.__console__
- logger = RegistrationStatisticsLogger(console, output_in_place)
- logger.start()
-
- solution = None
-
- hash_rates = [0] * n_samples # The last n true hash_rates
- weights = [alpha_ ** i for i in range(n_samples)] # weights decay by alpha
-
- while not wallet.is_registered(subtensor):
- # Wait until a solver finds a solution
- try:
- solution = solution_queue.get(block=True, timeout=0.25)
- if solution is not None:
- break
- except Empty:
- # No solution found, try again
- pass
-
- # check for new block
- old_block_number = check_for_newest_block_and_update(
- subtensor = subtensor,
- old_block_number=old_block_number,
- curr_diff=curr_diff,
- curr_block=curr_block,
- curr_block_num=curr_block_num,
- curr_stats=curr_stats,
- update_curr_block=update_curr_block,
- check_block=check_block,
- solvers=solvers
- )
-
- num_time = 0
- for finished_queue in finished_queues:
- try:
- proc_num = finished_queue.get(timeout=0.1)
- num_time += 1
-
- except Empty:
- continue
-
- time_now = time.time() # get current time
- time_since_last = time_now - time_last # get time since last work block(s)
- if num_time > 0 and time_since_last > 0.0:
- # create EWMA of the hash_rate to make measure more robust
-
- hash_rate_ = (num_time * update_interval) / time_since_last
- hash_rates.append(hash_rate_)
- hash_rates.pop(0) # remove the 0th data point
- curr_stats.hash_rate = sum([hash_rates[i]*weights[i] for i in range(n_samples)])/(sum(weights))
-
- # update time last to now
- time_last = time_now
-
- curr_stats.time_average = (curr_stats.time_average*curr_stats.rounds_total + curr_stats.time_spent)/(curr_stats.rounds_total+num_time)
- curr_stats.rounds_total += num_time
-
- # Update stats
- curr_stats.time_spent = time_since_last
- new_time_spent_total = time_now - start_time_perpetual
- curr_stats.hash_rate_perpetual = (curr_stats.rounds_total*update_interval)/ new_time_spent_total
- curr_stats.time_spent_total = new_time_spent_total
-
- # Update the logger
- logger.update(curr_stats, verbose=log_verbose)
-
- # exited while, solution contains the nonce or wallet is registered
- stopEvent.set() # stop all other processes
- logger.stop()
-
- # terminate and wait for all solvers to exit
- terminate_workers_and_wait_for_exit(solvers)
-
- return solution
-
-
-@backoff.on_exception(backoff.constant,
- Exception,
- interval=1,
- max_tries=3)
-def get_block_with_retry(subtensor: 'bittensor.Subtensor') -> Tuple[int, int, bytes]:
- block_number = subtensor.get_current_block()
- difficulty = subtensor.difficulty
- block_hash = subtensor.substrate.get_block_hash( block_number )
- if block_hash is None:
- raise Exception("Network error. Could not connect to substrate to get block hash")
- return block_number, difficulty, block_hash
-
-
-class UsingSpawnStartMethod():
- def __init__(self, force: bool = False):
- self._old_start_method = None
- self._force = force
-
- def __enter__(self):
- self._old_start_method = multiprocessing.get_start_method(allow_none=True)
- if self._old_start_method == None:
- self._old_start_method = 'spawn' # default to spawn
-
- multiprocessing.set_start_method('spawn', force=self._force)
-
- def __exit__(self, *args):
- # restore the old start method
- multiprocessing.set_start_method(self._old_start_method, force=True)
-
-
-def check_for_newest_block_and_update(
- subtensor: 'bittensor.Subtensor',
- old_block_number: int,
- curr_diff: multiprocessing.Array,
- curr_block: multiprocessing.Array,
- curr_block_num: multiprocessing.Value,
- update_curr_block: Callable,
- check_block: 'multiprocessing.Lock',
- solvers: List[Solver],
- curr_stats: RegistrationStatistics
- ) -> int:
- """
- Checks for a new block and updates the current block information if a new block is found.
- Args:
- subtensor (:obj:`bittensor.Subtensor`, `required`):
- The subtensor object to use for getting the current block.
- old_block_number (:obj:`int`, `required`):
- The old block number to check against.
- curr_diff (:obj:`multiprocessing.Array`, `required`):
- The current difficulty as a multiprocessing array.
- curr_block (:obj:`multiprocessing.Array`, `required`):
- Where the current block is stored as a multiprocessing array.
- curr_block_num (:obj:`multiprocessing.Value`, `required`):
- Where the current block number is stored as a multiprocessing value.
- update_curr_block (:obj:`Callable`, `required`):
- A function that updates the current block.
- check_block (:obj:`multiprocessing.Lock`, `required`):
- A mp lock that is used to check for a new block.
- solvers (:obj:`List[Solver]`, `required`):
- A list of solvers to update the current block for.
- curr_stats (:obj:`RegistrationStatistics`, `required`):
- The current registration statistics to update.
- Returns:
- (int) The current block number.
- """
- block_number = subtensor.get_current_block()
- if block_number != old_block_number:
- old_block_number = block_number
- # update block information
- block_hash = subtensor.substrate.get_block_hash( block_number)
- while block_hash == None:
- block_hash = subtensor.substrate.get_block_hash( block_number)
- block_bytes = block_hash.encode('utf-8')[2:]
- difficulty = subtensor.difficulty
-
- update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, difficulty, check_block)
- # Set new block events for each solver
-
- for worker in solvers:
- worker.newBlockEvent.set()
-
- # update stats
- curr_stats.block_number = block_number
- curr_stats.block_hash = block_hash
- curr_stats.difficulty = difficulty
-
- return old_block_number
-
-
-def solve_for_difficulty_fast_cuda( subtensor: 'bittensor.Subtensor', wallet: 'bittensor.Wallet', output_in_place: bool = True, update_interval: int = 50_000, TPB: int = 512, dev_id: Union[List[int], int] = 0, n_samples: int = 10, alpha_: float = 0.80, log_verbose: bool = False ) -> Optional[POWSolution]:
- """
- Solves the registration fast using CUDA
- Args:
- subtensor: bittensor.Subtensor
- The subtensor node to grab blocks
- wallet: bittensor.Wallet
- The wallet to register
- output_in_place: bool
- If true, prints the output in place, otherwise prints to new lines
- update_interval: int
- The number of nonces to try before checking for more blocks
- TPB: int
- The number of threads per block. CUDA param that should match the GPU capability
- dev_id: Union[List[int], int]
- The CUDA device IDs to execute the registration on, either a single device or a list of devices
- n_samples: int
- The number of samples of the hash_rate to keep for the EWMA
- alpha_: float
- The alpha for the EWMA for the hash_rate calculation
- log_verbose: bool
- If true, prints more verbose logging of the registration metrics.
- Note: The hash rate is calculated as an exponentially weighted moving average in order to make the measure more robust.
- """
- if isinstance(dev_id, int):
- dev_id = [dev_id]
- elif dev_id is None:
- dev_id = [0]
-
- if update_interval is None:
- update_interval = 50_000
-
- if not torch.cuda.is_available():
- raise Exception("CUDA not available")
-
- limit = int(math.pow(2,256)) - 1
-
- # Set mp start to use spawn so CUDA doesn't complain
- with UsingSpawnStartMethod(force=True):
- curr_block = multiprocessing.Array('h', 64, lock=True) # byte array
- curr_block_num = multiprocessing.Value('i', 0, lock=True) # int
- curr_diff = multiprocessing.Array('Q', [0, 0], lock=True) # [high, low]
-
- ## Create a worker per CUDA device
- num_processes = len(dev_id)
-
- # Establish communication queues
- stopEvent = multiprocessing.Event()
- stopEvent.clear()
- solution_queue = multiprocessing.Queue()
- finished_queues = [multiprocessing.Queue() for _ in range(num_processes)]
- check_block = multiprocessing.Lock()
-
- # Start workers
- solvers = [ CUDASolver(i, num_processes, update_interval, finished_queues[i], solution_queue, stopEvent, curr_block, curr_block_num, curr_diff, check_block, limit, dev_id[i], TPB)
- for i in range(num_processes) ]
-
-
- # Get first block
- block_number = subtensor.get_current_block()
- difficulty = subtensor.difficulty
- block_hash = subtensor.substrate.get_block_hash( block_number )
- while block_hash == None:
- block_hash = subtensor.substrate.get_block_hash( block_number )
- block_bytes = block_hash.encode('utf-8')[2:]
- old_block_number = block_number
-
- # Set to current block
- update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, difficulty, check_block)
-
- # Set new block events for each solver to start at the initial block
- for worker in solvers:
- worker.newBlockEvent.set()
-
- for worker in solvers:
- worker.start() # start the solver processes
-
- start_time = time.time() # time that the registration started
- time_last = start_time # time that the last work blocks completed
-
- curr_stats = RegistrationStatistics(
- time_spent_total = 0.0,
- time_average = 0.0,
- rounds_total = 0,
- time_spent = 0.0,
- hash_rate_perpetual = 0.0,
- hash_rate = 0.0, # EWMA hash_rate (H/s)
- difficulty = difficulty,
- block_number = block_number,
- block_hash = block_hash
- )
-
- start_time_perpetual = time.time()
-
- console = bittensor.__console__
- logger = RegistrationStatisticsLogger(console, output_in_place)
- logger.start()
-
- hash_rates = [0] * n_samples # The last n true hash_rates
- weights = [alpha_ ** i for i in range(n_samples)] # weights decay by alpha
-
- solution = None
- while not wallet.is_registered(subtensor):
- # Wait until a solver finds a solution
- try:
- solution = solution_queue.get(block=True, timeout=0.15)
- if solution is not None:
- break
- except Empty:
- # No solution found, try again
- pass
-
- # check for new block
- old_block_number = check_for_newest_block_and_update(
- subtensor = subtensor,
- curr_diff=curr_diff,
- curr_block=curr_block,
- curr_block_num=curr_block_num,
- old_block_number=old_block_number,
- curr_stats=curr_stats,
- update_curr_block=update_curr_block,
- check_block=check_block,
- solvers=solvers
- )
-
- num_time = 0
- # Get times for each solver
- for finished_queue in finished_queues:
- try:
- proc_num = finished_queue.get(timeout=0.1)
- num_time += 1
-
- except Empty:
- continue
-
- time_now = time.time() # get current time
- time_since_last = time_now - time_last # get time since last work block(s)
- if num_time > 0 and time_since_last > 0.0:
- # create EWMA of the hash_rate to make measure more robust
-
- hash_rate_ = (num_time * TPB * update_interval) / time_since_last
- hash_rates.append(hash_rate_)
- hash_rates.pop(0) # remove the 0th data point
- curr_stats.hash_rate = sum([hash_rates[i]*weights[i] for i in range(n_samples)])/(sum(weights))
-
- # update time last to now
- time_last = time_now
-
- curr_stats.time_average = (curr_stats.time_average*curr_stats.rounds_total + curr_stats.time_spent)/(curr_stats.rounds_total+num_time)
- curr_stats.rounds_total += num_time
-
- # Update stats
- curr_stats.time_spent = time_since_last
- new_time_spent_total = time_now - start_time_perpetual
- curr_stats.hash_rate_perpetual = (curr_stats.rounds_total * (TPB * update_interval))/ new_time_spent_total
- curr_stats.time_spent_total = new_time_spent_total
-
- # Update the logger
- logger.update(curr_stats, verbose=log_verbose)
-
- # exited while, found_solution contains the nonce or wallet is registered
-
- stopEvent.set() # stop all other processes
- logger.stop()
-
- # terminate and wait for all solvers to exit
- terminate_workers_and_wait_for_exit(solvers)
-
- return solution
-
-
-def terminate_workers_and_wait_for_exit(workers: List[multiprocessing.Process]) -> None:
- for worker in workers:
- worker.terminate()
- worker.join()
-
-
-def create_pow(
- subtensor,
- wallet,
- output_in_place: bool = True,
- cuda: bool = False,
- dev_id: Union[List[int], int] = 0,
- tpb: int = 256,
- num_processes: int = None,
- update_interval: int = None,
- log_verbose: bool = False
- ) -> Optional[Dict[str, Any]]:
- if cuda:
- solution: POWSolution = solve_for_difficulty_fast_cuda( subtensor, wallet, output_in_place=output_in_place, \
- dev_id=dev_id, TPB=tpb, update_interval=update_interval, log_verbose=log_verbose
- )
- else:
- solution: POWSolution = solve_for_difficulty_fast( subtensor, wallet, output_in_place=output_in_place, \
- num_processes=num_processes, update_interval=update_interval, log_verbose=log_verbose
- )
-
- return None if solution is None else {
- 'nonce': solution.nonce,
- 'difficulty': solution.difficulty,
- 'block_number': solution.block_number,
- 'work': binascii.hexlify(solution.seal)
- }
diff --git a/commune/modules/bittensor/utils/stats.py b/commune/modules/bittensor/utils/stats.py
deleted file mode 100644
index b83e49507..000000000
--- a/commune/modules/bittensor/utils/stats.py
+++ /dev/null
@@ -1,84 +0,0 @@
-""" A exponential moving average that updates values based on time since last update.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import time
-
-class timed_rolling_avg():
- """ A exponential moving average that updates values based on time since last update.
- """
- def __init__(self, initial_value, alpha):
- self.value = initial_value
- self.alpha = alpha
- self.last_update = time.time()
-
- def update(self, new_value):
- """ Update self.value (the moving average) with the new_value
- """
- now = time.time()
- time_delta = now - self.last_update
- self.last_update = now
- new_value = new_value / time_delta
- self.value = (1 - self.alpha) * self.value + self.alpha * new_value
-
-class AmountPerSecondRollingAverage():
- """ A exponential moving average that counts quantity per second.
- """
- def __init__(self, initial_value=0, alpha=0.1):
- self.value = initial_value
- self.alpha = alpha
- self.last_update = None
-
- def event(self, amount):
- """ Update self.value (the moving average) with the new_value
- """
- if self.last_update == None:
- self.last_update = time.time()
- else:
- now = time.time()
- time_delta = now - self.last_update
- self.last_update = now
- new_value = amount / time_delta
- self.value = (1 - self.alpha) * self.value + self.alpha * new_value
-
- def get(self) -> float:
- return float(self.value)
-
-
-class EventsPerSecondRollingAverage():
- """ A exponential moving average that counts the number of events per second.
- """
- def __init__(self, initial_value, alpha):
- self.value = initial_value
- self.alpha = alpha
- self.last_update = None
-
- def event(self):
- """ Update self.value (the moving average) with the new_value
- """
- if self.last_update == None:
- self.last_update = time.time()
- else:
- now = time.time()
- time_delta = now - self.last_update
- self.last_update = now
- new_value = 1 / time_delta
- self.value = (1 - self.alpha) * self.value + self.alpha * new_value
-
- def get(self) -> float:
- return float(self.value)
diff --git a/commune/modules/bittensor/utils/test_utils.py b/commune/modules/bittensor/utils/test_utils.py
deleted file mode 100644
index fdaa1bda9..000000000
--- a/commune/modules/bittensor/utils/test_utils.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import socket
-from random import randint
-from typing import Set
-
-max_tries = 10
-
-
-def get_random_unused_port(allocated_ports: Set = set()):
- def port_in_use(port: int) -> bool:
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
- return s.connect_ex(("localhost", port)) == 0
-
- tries = 0
- while tries < max_tries:
- tries += 1
- port = randint(2**14, 2**16 - 1)
-
- if port not in allocated_ports and not port_in_use(port):
- allocated_ports.add(port)
- return port
-
- raise RuntimeError(f"Tried {max_tries} random ports and could not find an open one")
diff --git a/commune/modules/bittensor/utils/tokenizer_utils.py b/commune/modules/bittensor/utils/tokenizer_utils.py
deleted file mode 100644
index e889b96e0..000000000
--- a/commune/modules/bittensor/utils/tokenizer_utils.py
+++ /dev/null
@@ -1,1423 +0,0 @@
-""" Utils for tokenizer equivalence checking, logit translation, etc.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import torch
-
-from typing import List, Dict, Tuple, Any, Union
-from transformers import PreTrainedTokenizerBase
-
-EPSILON = 1e-40
-
-
-def get_tokenizer_alignment_splits(offset_mapping: List[tuple], offset_mapping_std: List[tuple]) -> Dict[int, tuple]:
- r"""
- Calculates split depths necessary for tokens to align input offsets to standard offsets.
- Only input offsets may be split, not standard offsets, to create one-to-one, one-to-many, or many-to-one
- token alignments between input-to-standard tokenization.
- Allows for multiple depth splits on a token.
- Args:
- offset_mapping (:obj:`List[tuple]`, `required`):
- Tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...].
- offset_mapping_std (:obj:`List[tuple]`, `required`):
- Standard tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...]
-
- Returns:
- splits (:obj:`Dict[int, tuple]`, `required`):
- For tokens that have to be split, {Token index: (split depth 1, split depth 2, ...), ...}.
- """
-
- splits = {}
- idx = 0 # index of token segment (server tokenization)
- idx_std = 0 # index of token segment (standard tokenization)
-
- right = offset_mapping[idx][1] # first right edge
- right_std = offset_mapping_std[idx_std][1] # first std right edge
-
- while (idx + 1 < len(offset_mapping) and
- offset_mapping[idx + 1][1] == right): # ignore overlapping tokens
- idx += 1
-
- while (idx_std + 1 < len(offset_mapping_std) and
- offset_mapping_std[idx_std + 1][1] == right_std): # ignore overlapping tokens
- idx_std += 1
-
- segment_count = 1 # keep count of segments traversed,
- segment_count_std = 1 # to track one-to-many, many-to-one conditions
-
- while idx < len(offset_mapping) and idx_std < len(offset_mapping_std):
- if right < right_std:
- # Examples: [|] edge, [\] next edge, [.] split
- # (45, 49)
- # (45, 48) (48, 51) std
- # | .| \
- # | | |
- if segment_count == 1 and segment_count_std > 1: # prevent many-to-many
- # | . | \
- # | | | | |
- left = offset_mapping[idx][0]
- left_std = offset_mapping_std[idx_std][0]
- splits.setdefault(idx, [])
- splits[idx] += [left_std - left] # server token, split depth
- segment_count_std = 1
- continue
-
- idx += 1
- if idx < len(offset_mapping):
- right = offset_mapping[idx][1]
- segment_count += 1
-
- while (idx + 1 < len(offset_mapping) and
- offset_mapping[idx + 1][1] == right): # ignore right-aligned overlapping tokens
- idx += 1
-
- elif right_std < right:
- if segment_count_std == 1 and segment_count > 1: # prevent many-to-many
- # Examples: [|] edge, [\] next edge, [.] split
- # | | | | . |
- # | | \
-
- # (775, 778, 781, 788, 791)
- # (775, 782, 785, 795) std
- # | | |. . | | allow for multiple splits on a single token
- # | | | |
- left = offset_mapping[idx][0]
- splits.setdefault(idx, [])
- splits[idx] += [right_std - left] # server token, split depth
- segment_count = 1
- segment_count_std = 0
-
- idx_std += 1
- if idx_std < len(offset_mapping_std):
- right_std = offset_mapping_std[idx_std][1]
- segment_count_std += 1
-
- while (idx_std + 1 < len(offset_mapping_std) and
- offset_mapping_std[idx_std + 1][1] == right_std): # ignore right-aligned overlapping tokens
- idx_std += 1
-
- else: # right == right_std
- idx += 1
- if idx < len(offset_mapping):
- right = offset_mapping[idx][1]
- segment_count = 1
-
- idx_std += 1
- if idx_std < len(offset_mapping_std):
- right_std = offset_mapping_std[idx_std][1]
- segment_count_std = 1
-
- while (idx + 1 < len(offset_mapping) and
- offset_mapping[idx + 1][1] == right): # ignore right-aligned overlapping tokens
- idx += 1
-
- while (idx_std + 1 < len(offset_mapping_std) and
- offset_mapping_std[idx_std + 1][1] == right_std): # ignore right-aligned overlapping tokens
- idx_std += 1
-
- continue
-
- for idx in splits:
- splits[idx] = tuple(splits[idx]) # to enable hashable depths for split_map_cache keying
-
- return splits
-
-
-def get_tokenizer_sequence_mappings(offset_mapping: List[tuple], offset_mapping_std: List[tuple]) -> List[tuple]:
- r"""
- Greedily determine the one-to-one, one-to-many, or many-to-one token alignments
- between input-to-standard tokenizations.
- Disallow many-to-many mappings, but allow for right-aligned overlapping tokens.
- Args:
- offset_mapping (:obj:`List[tuple]`, `required`):
- Tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...].
- offset_mapping_std (:obj:`List[tuple]`, `required`):
- Standard tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...]
-
- Returns:
- mappings (:obj:`List[tuple]`, `required`):
- List of mapping tuples:
- [tuple( right_idx, right_idx_std,
- segment_count_base, segment_count_std_base,
- segment_count_overlap, segment_count_std_overlap), ...]
- """
- mappings = []
-
- idx = 0 # index of token segment (server tokenization)
- idx_std = 0 # index of token segment (standard tokenization)
-
- right = offset_mapping[idx][1] # first right edge
- right_std = offset_mapping_std[idx_std][1] # first std right edge
-
- segment_count = 1 # keep count of segments traversed,
- segment_count_std = 1 # to track one-to-many, many-to-one conditions
- segment_count_overlap = 0 # keep count of overlapping segments
- segment_count_std_overlap = 0
-
- while (idx + 1 < len(offset_mapping) and
- offset_mapping[idx + 1][1] == right): # ignore overlapping tokens
- idx += 1
- segment_count_overlap += 1
-
- while (idx_std + 1 < len(offset_mapping_std) and
- offset_mapping_std[idx_std + 1][1] == right_std): # ignore overlapping tokens
- idx_std += 1
- segment_count_std_overlap += 1
-
- while idx < len(offset_mapping) and idx_std < len(offset_mapping_std):
- if right < right_std:
- if segment_count == 1 and segment_count_std > 1:
- # Examples: [|] edge, [\] next edge, [.] split
- # | . | \
- # | | | | |
- print('Unaligned: Expected an aligned std edge.')
- print('idx, idx_std, right, right_std, segment_count, segment_count_std')
- print(idx, idx_std, right, right_std, segment_count, segment_count_std)
-
- idx += 1
- if idx < len(offset_mapping):
- right = offset_mapping[idx][1]
- segment_count += 1
-
- while (idx + 1 < len(offset_mapping) and
- offset_mapping[idx + 1][1] == right): # ignore overlapping tokens
- idx += 1
- segment_count_overlap += 1
-
- elif right_std < right:
- if segment_count_std == 1 and segment_count > 1:
- # Examples: [|] edge, [\] next edge, [.] split
- # | | | | . |
- # | | \
- print('Unaligned: Expected an aligned edge.')
- print('idx, idx_std, right, right_std, segment_count, segment_count_std')
- print(idx, idx_std, right, right_std, segment_count, segment_count_std)
-
- idx_std += 1
- if idx_std < len(offset_mapping_std):
- right_std = offset_mapping_std[idx_std][1]
- segment_count_std += 1
-
- while (idx_std + 1 < len(offset_mapping_std) and
- offset_mapping_std[idx_std + 1][1] == right_std): # ignore overlapping tokens
- idx_std += 1
- segment_count_std_overlap += 1
-
- else: # right == right_std
- mappings += [(idx, idx_std, segment_count, segment_count_std,
- segment_count_overlap, segment_count_std_overlap)]
-
- segment_count_overlap = 0
- segment_count_std_overlap = 0
-
- idx += 1
- if idx < len(offset_mapping):
- right = offset_mapping[idx][1]
- segment_count = 1
-
- idx_std += 1
- if idx_std < len(offset_mapping_std):
- right_std = offset_mapping_std[idx_std][1]
- segment_count_std = 1
-
- while (idx + 1 < len(offset_mapping) and
- offset_mapping[idx + 1][1] == right): # ignore overlapping tokens
- idx += 1
- segment_count_overlap += 1
-
- while (idx_std + 1 < len(offset_mapping_std) and
- offset_mapping_std[idx_std + 1][1] == right_std): # ignore overlapping tokens
- idx_std += 1
- segment_count_std_overlap += 1
- continue
-
- mappings += [(len(offset_mapping), len(offset_mapping_std), 1, 1, 0, 0)] # validation segment
-
- return mappings
-
-
-def get_tokenizer_depth_split_map(tokenizer: PreTrainedTokenizerBase,
- depths: tuple) -> List[Dict[str, torch.LongTensor]]:
- r"""
- Split individual token strings at specified depths, retokenize each resulting segment,
- keep only the first token of each segment (if there is one).
- Purpose is to provide targets for scattering probabilities when a single distribution requires a depth split.
- Args:
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Tokenizer.
- depths (:obj:`tuple`, `required`):
- Tuple of depths at which tokens strings will be split.
-
- Returns:
- split_map (:obj:`List[Dict[str, torch.LongTensor]]`, `required`):
- """
- split_map = []
-
- phrases = tokenizer.batch_decode(range(tokenizer.vocab_len)) # list of variable len strings (one per token)
-
- # first part of the phrase up to distance characters
- split_phrases = [[phrase[:depths[0]] for phrase in phrases]]
- for i in range(len(depths)-1):
- # middle parts of the phrase from distance characters to end
- split_phrases += [[phrase[depths[i]:depths[i+1]] for phrase in phrases]]
- # right part of the phrase from distance characters to end
- split_phrases += [[phrase[depths[-1]:] for phrase in phrases]]
-
- for i, phrases in enumerate(split_phrases): # loop through left, middle, right phrase collections
- side_tokens = tokenizer(phrases)['input_ids'] # tokenize phrase collection
- tokens_lens = [len(p) for p in side_tokens] # get token lengths of each phrase
- from_idx = [i for i, l in enumerate(tokens_lens) if l > 0] # only non-zero len tokens list
- first_tokens = [side_tokens[i][0] for i in from_idx] # collect first tokens of each tokenized phrase
- # add dict for phrase collection, mapping from original index to first tokens of tokenized phrase substrings
- split_map += [{'from': torch.tensor(from_idx, dtype=torch.long),
- 'to': torch.tensor(first_tokens, dtype=torch.long)}]
-
- return split_map
-
-
-def split_probs(probs: torch.FloatTensor, split_map: List[Dict[str, torch.Tensor]]) -> torch.FloatTensor:
- r"""
- Split a given probability distribution over a tokenizer vocabulary, given a split_map
- of mappings from original tokens to target tokens at each depth of the split.
- Args:
- probs (:obj:`torch.FloatTensor`, `required`):
- [vocab_size] Input probability distribution over a tokenizer vocabulary.
- split_map (:obj:`List[Dict[str, torch.Tensor]]`, `required`):
- A split_map of mappings from original tokens to target tokens at each depth of the split.
-
- Returns:
- new_probs (:obj:`torch.FloatTensor`, `required`):
- [splits, vocab_size] A new tensor with resultant probability distribution at each index
- of the first dim, representing corresponding split depth.
- """
- splits = len(split_map) # how many parts to the depth split map, e.g. left, middle, right parts
- vocab_size = probs.shape[0] # retain input vocabulary size
- new_probs = torch.zeros((splits, vocab_size)).to(probs.device) # provision prob dist for each part
-
- for pos in range(splits): # loop through all parts of the split
- from_idx = split_map[pos]['from'] # from original string token index
- to_idx = split_map[pos]['to'] # to first token index of retokenized part string
- new_probs[pos].scatter_add_(0, to_idx, probs[from_idx]) # transfer probabilities to new part distributions
-
- return new_probs # [splits, vocab_size]
-
-
-def align_tokenizer_sequences(probs: torch.FloatTensor, offset_mapping: List[tuple], offset_mapping_std: List[tuple],
- tokenizer: PreTrainedTokenizerBase,
- split_map_cache: Dict[tuple, List[Dict[str, torch.Tensor]]],
- tokens: torch.LongTensor, tokens_std: torch.LongTensor) -> Tuple[torch.FloatTensor,
- List[tuple],
- torch.LongTensor]:
- r"""
- Align an input tokenization distribution to standard tokenization segments by depth-splitting
- the input distribution at greedily chosen locations. Prepares the input distribution for mapping to a standard
- distribution.
- Args:
- probs (:obj:`torch.FloatTensor`, `required`):
- [sequence_len, vocab_size] Input probability distribution over a tokenizer vocabulary.
- offset_mapping (:obj:`List[tuple]`, `required`):
- Tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...].
- offset_mapping_std (:obj:`List[tuple]`, `required`):
- Standard tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...]
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Source tokenizer.
- split_map_cache (:obj:`Dict[tuple, List[Dict[str, torch.Tensor]]]`, `required`):
- A dictionary of depths keying split_maps of mappings from original tokens to
- target tokens at each depth of the split.
- tokens (:obj:`torch.LongTensor`, `required`):
- [sequence_len] A sequence of tokens produced by the source tokenizer.
- tokens_std (:obj:`torch.LongTensor`, `required`):
- [std_sequence_len] A sequence of tokens produced by the standard tokenizer.
-
- Returns:
- aligned_probs (:obj:`torch.FloatTensor`, `required`):
- [new_sequence_len, vocab_size] Aligned probability distribution over a tokenizer vocabulary.
- aligned_offset_mapping (:obj:`List[tuple]`, `required`):
- Tokenizer aligned offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...].
- aligned_tokens (:obj:`torch.LongTensor`, `required`):
- A sequence of aligned tokens produced by the source tokenizer.
- """
- aligned_tokens = [] # to store new aligned tokens
- aligned_probs = [] # to store new aligned probability distributions
- aligned_offset_mapping = [] # to store new aligned offset mappings of aligned tokens
- splits = get_tokenizer_alignment_splits(offset_mapping, offset_mapping_std) # get necessary token split locations
-
- prev_idx = 0
- for idx in splits: # each source token index that must be split
- depths = splits[idx] # list of depths at which the token string must be split
- aligned_probs += [probs[prev_idx:idx]] # retain preceding token probabilities
- aligned_offset_mapping += offset_mapping[prev_idx:idx] # retain preceding offset mappings
- aligned_tokens += [tokens[prev_idx:idx]] # retain preceding tokens
-
- if depths not in split_map_cache:
- # add depths split to cache to reuse in future (split map calc is relatively time-consuming)
- split_map_cache[depths] = get_tokenizer_depth_split_map(tokenizer, depths)
-
- new_probs = split_probs(probs[idx], split_map_cache[depths]) # [splits, vocab_size] new split probabilities
- aligned_probs += [new_probs]
-
- text_idx = tokenizer.decode(tokens[idx])
-
- # === Left part ===
- new_tokens = tokenizer(text_idx[:depths[0]], add_special_tokens=False, return_tensors='pt')['input_ids'][0]
- aligned_tokens += [new_tokens[:1]]
- aligned_offset_mapping += [(offset_mapping[idx][0], offset_mapping[idx][0] + depths[0])]
-
- # === Middle parts ===
- for d in range(len(depths)-1):
- new_tokens = tokenizer(text_idx[depths[d]:depths[d+1]],
- add_special_tokens=False, return_tensors='pt')['input_ids'][0]
- aligned_tokens += [new_tokens[:1]]
- aligned_offset_mapping += [(offset_mapping[idx][0] + depths[d], offset_mapping[idx][0] + depths[d+1])]
-
- # == Right part ===
- new_tokens = tokenizer(text_idx[depths[-1]:], add_special_tokens=False, return_tensors='pt')['input_ids'][0]
- aligned_tokens += [new_tokens[:1]]
- aligned_offset_mapping += [(offset_mapping[idx][0] + depths[-1], offset_mapping[idx][1])]
-
- prev_idx = idx + 1
-
- aligned_probs += [probs[prev_idx:]] # retain remainder of tokens probabilities
- aligned_tokens += [tokens[prev_idx:]] # retain remainder of tokens
- aligned_offset_mapping += offset_mapping[prev_idx:] # retain remainder of offset mappings
-
- aligned_probs = torch.cat(aligned_probs, dim=0) # [sequence_len, vocab_size] assemble final probability tensor
- aligned_tokens = torch.cat(aligned_tokens, dim=0).long() # [sequence_len] assemble final token sequence
-
- return aligned_probs, aligned_offset_mapping, aligned_tokens
-
-
-def get_translation_map(from_tokenizer: PreTrainedTokenizerBase,
- to_tokenizer: PreTrainedTokenizerBase) -> Dict[str, Any]:
- r"""
- Map individual token phrases from a tokenizer to another tokenizer.
- Args:
- from_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- From tokenizer.
- to_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- To tokenizer.
-
- Returns:
- translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- with source index to target indices.
- """
- set_vocab_len(from_tokenizer)
- set_vocab_len(to_tokenizer)
-
- translation_map = {'lengths': {}}
-
- phrases = from_tokenizer.batch_decode(range(from_tokenizer.vocab_len)) # tokens to strings
-
- to_tokens = to_tokenizer(phrases)['input_ids'] # convert single token from-phrases to to-tokenization
- to_tokens_lens = [len(p) for p in to_tokens]
- unique_lens = set(to_tokens_lens)
- max_len = max(unique_lens)
- counts = torch.zeros((max_len, to_tokenizer.vocab_len), dtype=torch.long)
-
- for l in unique_lens: # each unique one-to-many mapping length
- from_idx = [i for i, k in enumerate(to_tokens_lens) if k == l] # find len l to-tokenizations
- subset = [to_tokens[i] for i in from_idx] # find len l to-tokenizations
- from_idx = torch.tensor(from_idx, dtype=torch.long) # [subset_size]
- to_idx = torch.tensor(subset, dtype=torch.long) # [subset_size, l]
- translation_map['lengths'][l] = {'from': from_idx,
- 'to': to_idx}
- # accumulate counts on tokens, to be used to divide probability mass over its channeled sequences
- counts[:l, :].scatter_add_(1, to_idx.T, torch.ones((l, len(subset)), dtype=torch.long))
-
- translation_map['counts'] = counts
- return translation_map
-
-
-def translate_one_to_many(probs_from: torch.FloatTensor, probs_to: torch.FloatTensor,
- translation_map: Dict[str, Any]) -> None:
- r"""
- Translate a single token probability distribution from a source tokenization to a
- sequence of probability distributions over a target tokenization.
- Args:
- probs_from (:obj:`torch.FloatTensor`, `required`):
- [vocab_size] Input probability distribution over a from-tokenizer vocabulary.
- probs_to (:obj:`torch.FloatTensor`, `required`):
- [many, vocab_size] Output probability distributions over a to-tokenizer vocabulary.
- translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- with source index to target indices.
-
- Returns:
-
- """
- many_len = probs_to.shape[0]
-
- # === Unroll single distribution into std sequence ===
- for i in range(many_len): # each unrolling step
- for map_len in translation_map['lengths'].keys(): # each one-to-many mapping length available
- if map_len < i + 1:
- continue # skip unrolling steps not available in a shorter mapping length
- from_idx = translation_map['lengths'][map_len]['from']
- to_idx = translation_map['lengths'][map_len]['to'].T # [map_len, subset_size_std]
- probs_to[i, :].scatter_add_(0, to_idx[i, :], probs_from[from_idx]) # add probs in-place
-
-
-def translate_many_to_one(probs_from: torch.FloatTensor, probs_to: torch.FloatTensor,
- translation_map: Dict[str, Any]) -> None:
- r"""
- Translate a sequence of token probability distributions from a source tokenization to a
- single token probability distribution over a target tokenization.
- Args:
- probs_from (:obj:`torch.FloatTensor`, `required`):
- [many, vocab_size] Input probability distributions over a from-tokenizer vocabulary.
- probs_to (:obj:`torch.FloatTensor`, `required`):
- [vocab_size] Output probability distribution over a to-tokenizer vocabulary.
- translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- with source index to target indices.
-
- Returns:
-
- """
- many_len = probs_from.shape[0]
- probs_from_copy = probs_from.clone() # will modify from-probabilities
-
- # === Spread probability mass over realized sequences ===
- counts = translation_map['counts'] # [max_len, vocab_size]
- translation_max_len = counts.shape[0] # maximum possible many-to-one length available in translation map
-
- if many_len <= translation_max_len:
- probs_from_copy /= counts[:many_len, :] # divide probability mass by amount of paths crossing each token
- else: # limit probs_from token depth to max_len
- probs_from_copy[:translation_max_len, :] /= counts
-
- # === Reverse map std token to source sequences, gather avg. sequence prob ===
- for map_len in translation_map['lengths'].keys(): # mutually exclusive over std tokens
- from_idx = translation_map['lengths'][map_len]['from'] # [subset_size_std] one std token
- to_idx = translation_map['lengths'][map_len]['to'].T # [map_len, subset_size_std] many server token seq
- if many_len < map_len: # sequence beyond segment_count has min probability 0
- to_idx = to_idx[:many_len, :] # [segment_count, subset_size_std]
- server_seq_tokens = probs_from_copy.gather(1, to_idx) # [map_len, subset_size_std] gather sequences
- probs_to[from_idx] = server_seq_tokens.sum(dim=0) / map_len # [subset_size_std] in-place average approx.
-
-
-def translate_tokenizer_probs(probs: torch.FloatTensor, probs_std: torch.FloatTensor,
- offset_mapping: List[tuple], offset_mapping_std: List[tuple],
- tokenizer: PreTrainedTokenizerBase, std_tokenizer: PreTrainedTokenizerBase,
- split_map_cache: Dict[tuple, List[Dict[str, torch.Tensor]]],
- to_translation_map: Dict[str, Any], from_translation_map: Dict[str, Any],
- tokens: torch.LongTensor, tokens_std: torch.LongTensor) -> None:
- r"""
- Translates source token probability distributions to target probability distributions, by
- aligning segments through source token splits, then greedily performing one-to-one,
- one-to-many, many-to-one distribution mappings.
- Args:
- probs (:obj:`torch.FloatTensor`, `required`):
- [sequence_len, vocab_size] Input probability distribution over a source tokenizer vocabulary.
- probs_std (:obj:`torch.FloatTensor`, `required`):
- [std_sequence_len, std_vocab_size] Output probability distribution over a target tokenizer vocabulary.
- Reference that will be written in-place.
- offset_mapping (:obj:`List[tuple]`, `required`):
- Tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...].
- offset_mapping_std (:obj:`List[tuple]`, `required`):
- Standard tokenizer offset mappings for a specific sequence [(left_0, right_0), (left_1, right_1), ...]
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Source tokenizer.
- std_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Standard/target tokenizer.
- split_map_cache (:obj:`Dict[tuple, List[Dict[str, torch.Tensor]]]`, `required`):
- A dictionary of depths keying split_maps of mappings from original tokens to
- target tokens at each depth of the split. Adds split_maps to cache for faster future recall.
- tokens (:obj:`torch.LongTensor`, `required`):
- [sequence_len] A sequence of tokens produced by the source tokenizer.
- tokens_std (:obj:`torch.LongTensor`, `required`):
- [std_sequence_len] A sequence of tokens produced by the standard tokenizer.
- to_translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- with source index to target indices.
- from_translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- from target index to source indices.
-
- Returns:
-
- """
- # === Align tokenized sequences via source token splitting ===
- result = align_tokenizer_sequences(probs, offset_mapping, offset_mapping_std,
- tokenizer, split_map_cache, tokens.cpu(), tokens_std.cpu())
- aligned_probs, aligned_offset_mapping, aligned_tokens = result
-
- # === Get one-to-many / many-to-one mappings ===
- mappings = get_tokenizer_sequence_mappings(aligned_offset_mapping, offset_mapping_std)
-
- # === Perform probability mappings ===
- for (right_idx, right_idx_std, segment_count_base, segment_count_std_base,
- segment_count_overlap, segment_count_std_overlap) in mappings[1:]: # don't map start token
-
- segment_count = segment_count_base + segment_count_overlap # calculate effective segments length
- segment_count_std = segment_count_std_base + segment_count_std_overlap # calculate effective segments length
-
- # === One-to-many / one-to-one mapping ===
- if segment_count_base == 1:
- start_idx_std = right_idx_std - segment_count_std # calculate starting index
-
- translate_one_to_many(aligned_probs[right_idx-1],
- probs_std[start_idx_std:start_idx_std+segment_count_std],
- to_translation_map)
-
- # === Many-to-one mapping ===
- elif segment_count_std_base == 1: # many-to-one
- start_idx = right_idx - segment_count # calculate starting index
-
- translate_many_to_one(aligned_probs[start_idx:right_idx],
- probs_std[right_idx_std-1],
- from_translation_map)
-
- else:
- print('Undefined mapping.')
-
-
-def get_top_probs(probs: torch.FloatTensor, tokenizer: PreTrainedTokenizerBase, amount: int = 10) -> str:
- r"""
- Constructs output string with top amount of highest probability token strings.
- Used to display the top probabilities.
- Args:
- probs (:obj:`torch.FloatTensor`, `required`):
- [vocab_size] Probability distribution over a tokenizer vocabulary.
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Tokenizer.
- amount: (:obj:`int`, `optional`):
- Amount of top tokens to return
-
- Returns:
- string (:obj:`str`, `required`):
- Highest probability token strings, prob[token-string] ...
- """
- string = ''
-
- vals, indices = probs.sort(dim=-1, descending=True) # descending sort token probabilities
-
- for i in range(amount):
- string += '%.4f[%s] ' % (vals[i], tokenizer.decode(indices[i])) # prob[token-string]
-
- return string
-
-
-def translate_logits_to_probs_std(logits: torch.FloatTensor,
- offset_mapping: List[List[tuple]], offset_mapping_std: List[List[tuple]],
- tokenizer: PreTrainedTokenizerBase, std_tokenizer: PreTrainedTokenizerBase,
- split_map_cache: Dict[tuple, List[Dict[str, torch.Tensor]]],
- to_translation_map: Dict[str, Any], from_translation_map: Dict[str, Any],
- tokens: torch.LongTensor, tokens_std: torch.LongTensor,
- skip_equivalent: bool = True) -> torch.FloatTensor:
- r"""
- Translates source token logit scores to probability distributions over the standard tokenizer.
- Args:
- logits (:obj:`torch.FloatTensor`, `required`):
- [batch_size, sequence_len, vocab_size] Input source logits over a source tokenizer vocabulary.
- offset_mapping (:obj:`List[List[tuple]]`, `required`):
- Batch of tokenizer offset mappings
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- offset_mapping_std (:obj:`List[List[tuple]]`, `required`):
- Batch of standard tokenizer offset mappings
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Source tokenizer.
- std_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Standard/target tokenizer.
- split_map_cache (:obj:`Dict[tuple, List[Dict[str, torch.Tensor]]]`, `required`):
- A dictionary of depths keying split_maps of mappings from original tokens to
- target tokens at each depth of the split. Adds split_maps to cache for faster future recall.
- tokens (:obj:`torch.LongTensor`, `required`):
- [batch_size, sequence_len] A sequence of tokens produced by the source tokenizer.
- tokens_std (:obj:`torch.LongTensor`, `required`):
- [batch_size, std_sequence_len] A sequence of tokens produced by the standard tokenizer.
- to_translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- with source index to target indices.
- from_translation_map (:obj:`Dict[str, Any]`, `required`):
- Maps for each observed length, a source token to a token sequence of that length,
- from target index to source indices.
- skip_equivalent (:obj:`bool`, `optional`):
- Skips translation if tokenizer and std_tokenizer are equivalent.
-
- Returns:
- probs_std (:obj:`torch.FloatTensor`, `required`):
- [batch_size, std_sequence_len, std_vocab_size] Output probability distribution over the
- standard tokenizer vocabulary.
- """
- set_vocab_len(tokenizer)
- set_vocab_len(std_tokenizer)
-
- # === Check tokenizer equivalence / Skip if equivalent ===
- if skip_equivalent and check_tokenizer_equivalence(tokenizer, std_tokenizer):
- logits = logits.to(torch.float).to('cpu')
- probs = torch.softmax(logits, dim=2)
- return probs
-
- # === Get shape sizes ===
- batch_size, sequence_len, vocab_size = logits.shape
- std_sequence_len = tokens_std.shape[-1]
- std_vocab_size = std_tokenizer.vocab_len
-
- if tokenizer.vocab_len < vocab_size:
- logits = logits[..., :tokenizer.vocab_len]
- vocab_size = tokenizer.vocab_len
-
- # === Convert logits to probabilities ===
- logits = logits.to(torch.float).to('cpu')
- probs = torch.softmax(logits, dim=2) # [batch_size, sequence_len, vocab_size]
-
- if vocab_size < tokenizer.vocab_len: # fixes bug when model logits output is not full width
- padded_probs = torch.zeros((batch_size, sequence_len, tokenizer.vocab_len))
- padded_probs[..., :vocab_size] = probs
- probs = padded_probs
-
- # === Translate to probabilities over standard tokenizer ===
- probs_std = torch.zeros(batch_size, std_sequence_len, std_vocab_size)
- for b in range(batch_size):
- probs_b = probs[b][-len(offset_mapping[b]):] # remove left padding
- tokens_b = tokens[b][-len(offset_mapping[b]):] # remove left padding
- translate_tokenizer_probs(probs_b, probs_std[b], offset_mapping[b], offset_mapping_std[b],
- tokenizer, std_tokenizer,
- split_map_cache, to_translation_map, from_translation_map,
- tokens_b, tokens_std[b])
-
- # === Correct excess probability mass (haircut) ===
- probs_std_sum = probs_std.sum(dim=-1) # [batch_size, std_sequence_len]
- over = (probs_std_sum > 1)
- probs_std[over] /= probs_std_sum[over][:, None]
-
- # === Correct deficient probability mass (raise) ===
- probs_std_sum = probs_std.sum(dim=-1) # [batch_size, std_sequence_len]
- under = (probs_std_sum < 1)
- probs_std[under] += ((1 - probs_std_sum[under]) / probs_std[under].shape[-1])[:, None] # raise noise floor so sum 1
-
- return probs_std # [batch_size, std_sequence_len, std_vocab_size]
-
-
-def topk_token_phrases(logits: torch.Tensor, tokenizer: PreTrainedTokenizerBase,
- topk: int, ignore_index: int = -100) -> torch.Tensor:
- r"""
- Select topk tokenizer logits/phrases and include std_token_phrases counterparts (std_tokenization of token text)
- in topk_tensor output of shape [batch_size, (topk + 1), max_len], where max len of all phrase lists
- (with prob in front) is max_{b,k}(len([prob_k, tok_0_k, tok_1_k, ...])).
- The output topk_tensor also includes a floor_prob for each batch item. The floor probability is the
- mean probability of token phrases not captured in topk, required since the tokenizer vocab_size may
- not be known to the receiver.
- Requires prep_tokenizer(tokenizer, std_tokenizer) to set_std_token_phrases first, to make
- std_token_phrases available here.
- Args:
- logits (:obj:`torch.Tensor`, `required`):
- [batch_size, vocab_size] Input source logits for last token over a source tokenizer vocabulary.
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Source tokenizer (usually server tokenizer)
- topk (:obj:`int`, `required`):
- Amount of top phrases to expect (to check for mismatch)
- ignore_index (:obj:`int`, `optional`):
- Padding value to use for unfilled token positions in a shorter token phrase.
-
- Returns:
- topk_tensor (:obj:`torch.Tensor`, `required`):
- [batch_size, (topk + 1), max_len] tensor includes topk token probabilities (prob_k) + floor_prob
- in first column with gradients attached, with std_tokens in remaining columns with ignore_index padding.
- Content structure:
- [[[prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., ignore_index?],
- [prob_k=1_b=0, tok_0_k=1_b=0, tok_1_k=1_b=0, ..., ignore_index?],
- [...],
- [prob_floor_b=0, ignore_index, ..., ignore_index]],
- [[prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., ignore_index?],
- [prob_k=1_b=1, tok_0_k=1_b=1, tok_1_k=1_b=1, ..., ignore_index?],
- [...],
- [prob_floor_b=1, ignore_index, ..., ignore_index]],
- [...]]
- """
- # Get shape sizes
- batch_size, vocab_size = logits.shape # [batch_size, vocab_size] only last token prediction
-
- # Convert logits to probabilities
- logits = logits.float() # ensure further computations done in float32 for improved precision
- probs = torch.softmax(logits, dim=1) # [batch_size, vocab_size]
-
- # TopK phrase selection
- topk_probs, topk_indices = torch.topk(probs, topk) # topk probs and indices: [batch_size, topk]
-
- # === Calculate floor probability ===
- topk_pmass = topk_probs.sum(dim=-1) # [batch_size] topk probability mass
- remainder_pmass = torch.clamp(1 - topk_pmass, 1e-40, 1) # [batch_size] remainder probability mass
- floor_probs = remainder_pmass / (vocab_size - topk) # [batch_size]divide remainder
-
- # convert to list for faster iteration in list comprehension
- topk_probs_list = topk_probs.tolist()
- topk_indices_list = topk_indices.tolist()
- floor_probs_list = floor_probs.tolist()
-
- # === Construct topk phrases list ===
- probs = [] # collect probability tensors with gradients attached (to be grafted into topk_tensor)
- phrases = [] # form topk token phrases with prob prepend [prob, tok_0, tok_1, ... tok_n]
-
- for b in range(batch_size):
- # collect probability tensors with gradients attached (to be grafted into topk_tensor)
- probs += [topk_probs[b], floor_probs[b]] # [tensor(prob_k=0_b, prob_k=1_b, ...), tensor(prob_floor_b)]
-
- # form topk token phrases with prob prepend [prob, tok_0, tok_1, ... tok_n]
- phrases += [[prob] + tokenizer.std_token_phrases[i]
- for prob, i in zip(topk_probs_list[b], topk_indices_list[b])] # [prob_k, tok_0_k, tok_1_k, ...]
-
- # also add prob_floor for batch item
- phrases += [[floor_probs_list[b]]] # [prob_floor_b]
-
- # determine width of topk_tensor as max len of all phrase lists (with prob in front)
- max_len = max([len(p) for p in phrases]) # max_{b,k}(len([prob_k, tok_0_k, tok_1_k, ...]))
-
- # form single 2D tensor with all phrase and probs (typically to send to axon wire encoding)
- topk_tensor = torch.tensor([p + [ignore_index] * (max_len - len(p))
- for p in phrases]).to(logits.device) # [batch_size * (topk + 1), max_len]
-
- # grafting probability tensors into first column to attach gradients
- topk_tensor[:, 0] = torch.hstack(probs) # tensor([prob_k=0_b, prob_k=1_b, ..., prob_floor_b])
-
- topk_tensor = topk_tensor.reshape(batch_size, topk + 1, max_len) # [batch_size, (topk + 1), max_len] reshaped
-
- return topk_tensor # [batch_size, (topk + 1), max_len] (probability gradients attached in first column)
-
-
-def compact_topk_token_phrases(topk_tensor: torch.Tensor):
- r"""
- Compact 2D topk_tensor [batch_size, (topk + 1), max_len] by removing ignore_index padding, and also offset
- tokens by 2 to preserve [0, 1] for probabilities to allow for proper unraveling demarcated by
- probability boundaries.
- Args:
- topk_tensor (:obj:`torch.Tensor`, `required`):
- [batch_size, (topk + 1), max_len] tensor includes topk token probabilities (prob_k) + floor_prob
- in first column with gradients attached, with std_tokens in remaining columns with ignore_index padding.
- Content structure:
- [[[prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., ignore_index?],
- [prob_k=1_b=0, tok_0_k=1_b=0, tok_1_k=1_b=0, ..., ignore_index?],
- [...],
- [prob_floor_b=0, ignore_index, ..., ignore_index]],
- [[prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., ignore_index?],
- [prob_k=1_b=1, tok_0_k=1_b=1, tok_1_k=1_b=1, ..., ignore_index?],
- [...],
- [prob_floor_b=1, ignore_index, ..., ignore_index]],
- [...]]
-
- Returns:
- compact_topk (:obj:`torch.Tensor`, `required`):
- [sum_b(sum_k(len(phrase_k) + 1)_b)] Compacted 1-D tensor >= batch_size * (2 * topk + 1),
- since 2 * topk + 1: topk x [probability, token sequence (at least one token)] +
- floor probability (rest).
- Content structure:
- [prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., prob_k=1_b=0, tok_0_k=1_b=0, ..., prob_floor_b=0,
- prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., prob_k=1_b=1, tok_0_k=1_b=1, ..., prob_floor_b=1,
- ...]
- """
- topk_tensor_offset = topk_tensor.clone() # assume topk_tensor may be reused elsewhere so clone
- topk_tensor_offset[:, :, 1:] += 2 # add 2 to token ids to preserve [0, 1] for probabilities (in first column)
-
- flattened = topk_tensor_offset.flatten() # [batch_size * (topk + 1) * max_len] 1D tensor
- compact_topk = flattened[flattened > -1] # remove ignore_index < -1 padding to compact content
-
- return compact_topk # [>= batch_size * (2 * topk + 1)]
-
-
-def unravel_topk_token_phrases(compact_topk: torch.Tensor, topk: int, ignore_index: int = -100) -> torch.Tensor:
- r"""
- Unravel topk token phrases input_tensor from 1-D to [batch_size, (topk + 1), max_len] topk_tensor, which
- includes topk token probabilities (prob_k) + floor_prob in first column with gradients attached, with
- std_tokens in remaining columns with ignore_index padding.
- Args:
- compact_topk (:obj:`torch.Tensor`, `required`):
- [sum_b(sum_k(len(phrase_k) + 1)_b)] Compacted 1-D tensor >= batch_size * (2 * topk + 1),
- since 2 * topk + 1: topk x [probability, token sequence (at least one token)] +
- floor probability (rest).
- Content structure:
- [prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., prob_k=1_b=0, tok_0_k=1_b=0, ..., prob_floor_b=0,
- prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., prob_k=1_b=1, tok_0_k=1_b=1, ..., prob_floor_b=1,
- ...]
- topk (:obj:`int`, `required`):
- Amount of top phrases to expect (to check for mismatch)
- ignore_index (:obj:`int`, `optional`):
- Padding value to use for unfilled token positions in a shorter token phrase.
- Returns:
- topk_tensor (:obj:`torch.Tensor`, `required`):
- [batch_size, (topk + 1), max_len] tensor includes topk token probabilities (prob_k) + floor_prob
- in first column with gradients attached, with std_tokens in remaining columns with ignore_index padding.
- Content structure:
- [[[prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., ignore_index?],
- [prob_k=1_b=0, tok_0_k=1_b=0, tok_1_k=1_b=0, ..., ignore_index?],
- [...],
- [prob_floor_b=0, ignore_index, ..., ignore_index]],
- [[prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., ignore_index?],
- [prob_k=1_b=1, tok_0_k=1_b=1, tok_1_k=1_b=1, ..., ignore_index?],
- [...],
- [prob_floor_b=1, ignore_index, ..., ignore_index]],
- [...]]
- """
-
- atol = 1e-6 # absolute tolerance
- # Find probability markers (per batch item: topk phrase probabilities + floor_prob)
- prob_idx = torch.where((-atol < compact_topk) & (compact_topk < 1 + atol))[0] # 0 <= prob <= 1 [batch_size * (topk + 1)], expect token_ids >= 2
-
- batch_size = len(prob_idx) // (topk + 1) # (batch_size * (topk + floor)) / (topk + floor)
- assert batch_size * (topk + 1) == len(prob_idx), f'unravel_topk_token_phrases() probability marker failure: ' \
- f'{batch_size} * ({topk} + 1) != {len(prob_idx)}' # decoding irregularity otherwise
-
- probs = torch.clamp(compact_topk[prob_idx], 0, 1) # [batch_size * (topk + 1)] ensure probabilities within [0, 1]
- probs_sum = probs.reshape(batch_size, topk + 1).sum(dim=1) # [batch_size]
- assert torch.all((-atol < probs_sum) & (probs_sum < 1 + atol)), f'unravel_topk_token_phrases(): probs_sum not in [0, 1]'
-
- # Obtain phrase lengths and maximum phrase length
- phrase_len = prob_idx[1:] - prob_idx[:-1] # [batch_size * (topk + 1) - 1] length of each phrase
- phrase_len = torch.cat((phrase_len, torch.tensor([1]))) # [batch_size * (topk + 1)] prob_floor is always len=1
- max_len = phrase_len.max() # determine width of topk_tensor as max len of all phrase lists (with prob in front)
-
- # Initialize topk_tensor with ignore_index + 2, since decrement with 2 follows to remove token offset later
- topk_tensor = torch.ones((batch_size * (topk + 1), max_len), device=compact_topk.device)
- topk_tensor *= ignore_index + 2 # [batch_size * (topk + 1), max_len]
-
- # Insert phrases of each unique length as block into topk_tensor
- for unique_len in phrase_len.unique():
- if unique_len <= 1:
- continue # skip probability column, will be added afterward
-
- phrase_idx = torch.where(phrase_len == unique_len)[0] # phrase indices where phrase_len is unique_len
- compact_idx = prob_idx[phrase_idx] # indices in compact_topk
-
- # Create indexing block, add index for each phrase position, skip first (prob) position
- block_idx = [compact_idx + position for position in range(1, unique_len)] # incrementally add each position of phrase
- # transpose .t() ensures correct interleaving of consecutive positions:
- # [[phrase_a_1, phrase_a_2, ..., phrase_a_n], [phrase_b_1, phrase_b_2, ..., phrase_b_n], ...]
- block_idx = torch.vstack(block_idx).t().reshape(-1, unique_len - 1) # [-1, unique_len - 1] for all phrases with unique_len
-
- topk_tensor[phrase_idx, 1:unique_len] = compact_topk[block_idx] # slice selected phrases and copy into topk_tensor
-
- topk_tensor -= 2 # remove token offset, overwrites probability column, replace probabilities below
-
- # grafting probability tensors into first column to attach gradients
- topk_tensor[:, 0] = probs # tensor([prob_k=0_b, prob_k=1_b, ..., prob_floor_b])
-
- topk_tensor = topk_tensor.reshape(batch_size, topk + 1, max_len) # [batch_size, (topk + 1), max_len] reshaped
-
- return topk_tensor # [batch_size, (topk + 1), max_len]
-
-
-def phrase_cross_entropy(target_phrases: Union[List[List[int]], torch.Tensor],
- topk_tensor: torch.Tensor,
- ignore_index: int = -100, reduce=True, reduction='mean',
- vocab_size_min: int = 50257) -> Tuple[torch.Tensor, torch.Tensor]:
- r"""
- Calculates the cross entropy of a phrase prediction against a target phrase, so that this is a multi-token
- extension of typical cross entropy calculated for next token prediction.
- Args:
- target_phrases (:obj:`List[List[int]]`, `required`):
- [batch_size, *] Target phrases in standard token sequence list.
- topk_tensor (:obj:`torch.Tensor`, `required`):
- [batch_size, (topk + 1), max_len] tensor includes topk token probabilities (prob_k) + floor_prob
- in first column with gradients attached, with std_tokens in remaining columns with ignore_index padding.
- Content structure:
- [[[prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., ignore_index?],
- [prob_k=1_b=0, tok_0_k=1_b=0, tok_1_k=1_b=0, ..., ignore_index?],
- [...],
- [prob_floor_b=0, ignore_index, ..., ignore_index]],
- [[prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., ignore_index?],
- [prob_k=1_b=1, tok_0_k=1_b=1, tok_1_k=1_b=1, ..., ignore_index?],
- [...],
- [prob_floor_b=1, ignore_index, ..., ignore_index]],
- [...]]
- ignore_index (:obj:`int`, `optional`):
- Padding value to use for unfilled token positions in a shorter token phrase.
- reduce (:obj:`bool`, `optional`):
- Whether to reduce the cross entropy over the batch dimension.
- reduction (:obj:`str`, `optional`):
- Reduction function to perform when reduce is True.
- vocab_size_min (:obj:`int`, `optional`):
- Minimum server vocab_size expected, should set to nominal 50257,
- used to prevent the floor_probs from being too large.
- Returns:
- loss_val (:obj:`torch.Tensor`, `required`):
- Validation cross entropy loss, either scalar if reduce or [batch_size].
- loss (:obj:`torch.Tensor`, `required`):
- Phrase cross entropy loss, either scalar if reduce or [batch_size].
- """
-
- batch_size, topk_p1, max_len = topk_tensor.shape # [batch_size, (topk + 1), max_len]
- topk = topk_p1 - 1
-
- topk_tokens = topk_tensor[:, :-1, 1:].round().int() # [batch_size, topk, max_len - 1] Phrase tokens with ignore_index token for padding.
- topk_probs = topk_tensor[:, :-1, 0] # [batch_size, topk] Probabilities for each phrase in topk
- floor_probs = topk_tensor[:, -1, 0] # [batch_size] Floor probabilities as mean probability for non-topk tokens
-
- topk_probs = torch.clamp(topk_probs, 0, 1) # [batch_size, topk] ensure probabilities within [0, 1]
- floor_probs = torch.clamp(floor_probs, 0, 1) # [batch_size] ensure floor probabilities within [0, 1]
-
- # === Ensure total probability is 1 ===
- total_probs = topk_probs.sum(dim=-1) + max(0, vocab_size_min - topk) * floor_probs # [batch_size] total probs
- n_topk_probs = topk_probs / total_probs[:, None] # [batch_size, topk] normalized topk_probs
- n_floor_probs = floor_probs / total_probs # [batch_size] normalized floor_probs
-
- val_probs = torch.zeros(batch_size).to(topk_probs.device) # accumulate probabilities when first tokens match
- match_probs = torch.zeros(batch_size).to(topk_probs.device) # accumulate probabilities when sub target matches phrase
- for b in range(batch_size):
- target_phrase = target_phrases[b]
- if not isinstance(target_phrase, torch.Tensor):
- target_phrase = torch.tensor(target_phrases[b])
- if isinstance(target_phrase, torch.FloatTensor):
- target_phrase = target_phrase.round().int()
-
- match = (topk_tokens[b, :, 0] == target_phrase[0].item()) # bool where first tokens match (validation token)
- if match.sum() > 0:
- val_probs[b] = n_topk_probs[b, match].sum() # accumulate all matches
- else: # no matches
- val_probs[b] = n_floor_probs[b] # assume match is in non-topk tokens with avg floor_prob
-
- # === Integrate sub target matches ===
- check_len = min(max_len - 1, len(target_phrase))
- for c in range(1, check_len + 1): # progressively increase sub target length
- target = ignore_index * torch.ones(check_len, dtype=torch.int32).to(topk_tensor.device) # [-100, ..., -100]
- target[:c] = target_phrase[:c] # [tok0, tok1, ...tokc, -100, ..., -100]
-
- # Find sub target matches
- match = (topk_tokens[b, :, :check_len] == target)
- match_idx = torch.where(match.sum(dim=-1) == check_len)[0] # phrase indices which match sub target
-
- if len(match_idx): # at least one match
- match_probs[b] += n_topk_probs[b, match_idx].sum() # accumulate all matches
- else: # no matches
- match_probs[b] += n_floor_probs[b] # assume match is in non-topk tokens with avg floor_prob
-
- val_probs = torch.clamp(val_probs, 0, 1) # [batch_size] ensure 0 <= total probability <= 1
- loss_val = - torch.log(val_probs + 1e-40) # [batch_size] calculate cross entropy loss
-
- match_probs = torch.clamp(match_probs, 0, 1) # [batch_size] ensure 0 <= total probability <= 1
- loss = - torch.log(match_probs + 1e-40) # [batch_size] calculate cross entropy loss
-
- if reduce:
- if not hasattr(loss_val, reduction) or not hasattr(loss, reduction):
- raise RuntimeError(f'phase_cross_entropy(): Reduction function {reduction} not found.')
- loss_val = getattr(loss_val, reduction)()
- loss = getattr(loss, reduction)()
- if loss.numel() > 1:
- raise ValueError(f'phase_cross_entropy(): Expected reduction to scalar, obtained {loss.shape} instead.')
-
- return loss_val, loss
-
-
-def topk_tokens_to_vocab_size(topk_tensor: torch.Tensor, vocab_size_std: int, vocab_size_min: int = 50257) -> torch.Tensor:
- r"""
- Convert topk_tokens first token probabilities into a standard logits tensor shape [batch_size, vocab_size_std].
- Args:
- topk_tensor (:obj:`torch.Tensor`, `required`):
- [batch_size, (topk + 1), max_len] tensor includes topk token probabilities (prob_k) + floor_prob
- in first column with gradients attached, with std_tokens in remaining columns with ignore_index padding.
- Content structure:
- [[[prob_k=0_b=0, tok_0_k=0_b=0, tok_1_k=0_b=0, ..., ignore_index?],
- [prob_k=1_b=0, tok_0_k=1_b=0, tok_1_k=1_b=0, ..., ignore_index?],
- [...],
- [prob_floor_b=0, ignore_index, ..., ignore_index]],
- [[prob_k=0_b=1, tok_0_k=0_b=1, tok_1_k=0_b=1, ..., ignore_index?],
- [prob_k=1_b=1, tok_0_k=1_b=1, tok_1_k=1_b=1, ..., ignore_index?],
- [...],
- [prob_floor_b=1, ignore_index, ..., ignore_index]],
- [...]]
- vocab_size_std (:obj:`int`, `optional`):
- Standard tokenizer vocab_size for forming logits.
- vocab_size_min (:obj:`int`, `optional`):
- Minimum server vocab_size expected, should set to nominal 50257,
- used to prevent the floor_probs from being too large.
- Returns:
- logits (:obj:`torch.Tensor`, `required`):
- [batch_size, vocab_size_std] Standard logits.
- """
-
- batch_size, topk_p1, max_len = topk_tensor.shape # [batch_size, (topk + 1), max_len]
- topk = topk_p1 - 1
-
- topk_tokens = topk_tensor[:, :-1, 1].round().to(torch.int64) # [batch_size, topk] first tokens
- topk_probs = topk_tensor[:, :-1, 0] # [batch_size, topk] Probabilities for each phrase in topk
- floor_probs = topk_tensor[:, -1, 0] # [batch_size] Floor probabilities as mean probability for non-topk tokens
-
- topk_probs = torch.clamp(topk_probs, 0, 1) # [batch_size, topk] ensure probabilities within [0, 1]
- floor_probs = torch.clamp(floor_probs, 0, 1) # [batch_size] ensure floor probabilities within [0, 1]
-
- # === Ensure total probability is 1 ===
- total_probs = topk_probs.sum(dim=-1) + max(0, vocab_size_min - topk) * floor_probs # [batch_size] total probs
- n_topk_probs = topk_probs / total_probs[:, None] # [batch_size, topk] normalized topk_probs
-
- # === Convert to logits tensor ===
- probs = torch.zeros((batch_size, vocab_size_std)) # [batch_size, vocab_size_std]
- probs.scatter_add_(1, topk_tokens, n_topk_probs) # accumulate token probabilities onto logits tensor
-
- return probs # [batch_size, vocab_size_std]
-
-
-def check_tokenizer_equivalence(tokenizer_to_check: PreTrainedTokenizerBase,
- target_tokenizer: PreTrainedTokenizerBase) -> bool:
- r"""
- Is tokenizer_to_check equivalent to target_tokenizer?
- Args:
- tokenizer_to_check (:obj:`PreTrainedTokenizerBase`, `required`):
- Tokenizer to check for equivalence.
- target_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Target tokenizer to check equivalence against.
-
- Returns:
- result (:obj:`bool`, `required`)
- """
- set_vocab_len(tokenizer_to_check)
- set_vocab_len(target_tokenizer)
-
- if tokenizer_to_check.vocab_len != target_tokenizer.vocab_len:
- return False
-
- to_check_vocab = tokenizer_to_check.batch_decode(range(tokenizer_to_check.vocab_len))
- target_vocab = target_tokenizer.batch_decode(range(target_tokenizer.vocab_len))
-
- return to_check_vocab == target_vocab # indexed tokenizer vocabularies should match
-
-
-def prune_tokens(inputs: torch.FloatTensor, prune_len: int = 1, margin: int = 3):
- r"""
- Prune tokens from a batch of sequences randomly by removing prune_len tokens from each sequence,
- leaving the end margin intact.
- Args:
- inputs (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, seq_len)`, `required`):
- Tensor inputs to have tokens pruned.
- prune_len (:obj:`int`, `optional`):
- Number of tokens to prune from each validation input sequence.
- margin (:obj:`int`, `optional`):
- Number of tokens at the end of the sequence to leave unpruned.
- Returns:
- pruned_inputs (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, seq_len - prune_len)`, `required`)
- """
- seq_len = len(inputs[0])
- if prune_len <= 0:
- return inputs
- elif seq_len - margin < prune_len:
- prune_len = seq_len - margin
- pruned_inputs = []
- for b in range(len(inputs)):
- rand_index = torch.randperm(seq_len - margin)[:prune_len]
- mask = torch.ones(seq_len, dtype=torch.bool)
- mask[rand_index] = False
- pruned_inputs.append(inputs[b, mask])
-
- return torch.stack(pruned_inputs)
-
-
-def pad_offsets(offsets_batch: List[List[tuple]], source_offsets_batch: List[List[List[Any]]],
- pad_offsets_batch: List[List[List[Any]]]) -> List[List[List[Any]]]:
- r"""
- Pads specific tuples in offsets_batch, selected by source_offsets_batch with
- associated paddings in pad_offsets_batch.
- Purpose is typically to add padding to align two tokenization offsets at special tokens.
- Args:
- offsets_batch (:obj:`List[List[tuple]]`, `required`):
- Batch of full input tokenizer offset mappings to be used for alteration
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- source_offsets_batch (:obj:`List[List[List[Any]]]`, `required`):
- Batch of tokenizer offset mappings indicating replacement tuples in offsets_batch
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- pad_offsets_batch (:obj:`List[List[List[Any]]]`, `required`):
- Batch of offset paddings associated with each source_offsets_batch replacement tuple
- [[(left_pad_0, right_pad_0), (left_pad_1, right_pad_1), ...], ...].
-
- Returns:
- new_offsets_batch (:obj:`List[List[List[Any]]]`, `required`):
- Batch of padded full input tokenizer offset mappings
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- """
- new_offsets_batch = []
- batch_len = len(offsets_batch)
-
- for b in range(batch_len):
- new_offsets = []
- pad = 0
-
- idx = 0
- for left, right in offsets_batch[b]: # go through original offsets
- if idx < len(source_offsets_batch[b]):
- source_left, source_right = source_offsets_batch[b][idx]
- if left == source_left and right == source_right: # matching offset found
- pad_left, pad_right = pad_offsets_batch[b][idx]
- new_offsets += [(pad_left + pad, pad_right + pad)] # replace offsets with padded + accum. pad
- pad += pad_right - right
- idx += 1
- continue
- new_offsets += [(left + pad, right + pad)] # adjust original offsets w/ accum. pad
-
- new_offsets_batch += [new_offsets]
-
- return new_offsets_batch
-
-
-def find_offsets(string: str, substring: str) -> List[List[int]]:
- r"""
- Finds all the [start, end] offsets of substring in string.
- Assumes there is no overlap of substring, nor recursive overlap.
- Args:
- string (:obj:`str`, `required`):
- Main string to find offsets in.
- substring (:obj:`str`, `required`):
- Substring to search for in string.
-
- Returns:
- offsets (:obj:`List[List[int]]`, `required`):
- Offsets denoting the [start, end] positions of substring in string.
- """
- offsets = []
- idx = string.find(substring) # find first instance
- while idx != -1: # found an instance
- offsets += [[idx, idx + len(substring)]] # add offsets
- idx = string.find(substring, idx + len(substring)) # find next instance
-
- return offsets
-
-
-def replace_at_offsets(string: str, offsets: List[List[Any]]) -> Tuple[str, List[List[int]]]:
- r"""
- Replace indicated [left, right] offset positions with a new substring, by
- deleting [left, right] content and adding [left, left+len(substring)] substring,
- adjusting offsets incrementally.
- Assumes an incremental ordered, non-overlapping list of offsets, constructing
- the new string incrementally and recording new offsets.
- Args:
- string (:obj:`str`, `required`):
- Main string to perform replacements for.
- offsets (:obj:`List[List[Any]]`, `required`):
- Offsets where replacements are made with replacement substring
- [[left_0, right_0, substring_0], ...]
-
- Returns:
- new_string (:obj:`str`, `required`):
- New string where replacements were made.
- new_offsets (:obj:`List[List[Any]]`, `required`):
- New offsets where replacements are now located
- [[left_0, right_0], [left_1, right_1], ...]
- """
- new_string = ''
- new_offsets = []
-
- prev = 0
- for left, right, substring in offsets:
- new_string += string[prev:left] # retain preceding string
- new_left = len(new_string) # advance index
-
- new_string += substring # add new substring
- new_right = len(new_string)
-
- new_offsets += [[new_left, new_right]] # add offsets
-
- prev = right # advance index
-
- new_string += string[prev:]
-
- return new_string, new_offsets
-
-
-def get_special_token_pairings(from_tokenizer: PreTrainedTokenizerBase,
- to_tokenizer: PreTrainedTokenizerBase) -> Dict[str, str]:
- r"""
- Determines a prioritized matching of special token texts between two tokenizers.
- Purpose is to produce replacement pairs so special token test is correctly represented for target tokenizer.
- Args:
- from_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- From tokenizer.
- to_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- To tokenizer.
-
- Returns:
- pairings (:obj:`Dict[str, str]`, `required`):
- Prioritized dictionary of From_special_token_text -> To_special_token_text.
- """
- pairings = {}
-
- # some tokenizers e.g. GPT2 have the same text signifying BOS and EOS, while in other e.g. XGLM they differ
- # so prioritize EOS token first, since this seems to be the default context separator, e.g. XGLM, GerPT2, GPT2
- if ('eos_token' in from_tokenizer.special_tokens_map) and ('eos_token' in to_tokenizer.special_tokens_map):
- pairings[getattr(from_tokenizer, 'eos_token')] = getattr(to_tokenizer, 'eos_token')
-
- for special_token in from_tokenizer.special_tokens_map:
- if special_token in to_tokenizer.special_tokens_map:
- if getattr(from_tokenizer, special_token) not in pairings: # prevent priority overwrite
- pairings[getattr(from_tokenizer, special_token)] = getattr(to_tokenizer, special_token)
-
- return pairings
-
-
-def translate_special_token_text(text_batch: List[str], from_tokenizer: PreTrainedTokenizerBase,
- to_tokenizer: PreTrainedTokenizerBase) -> Tuple[List[str],
- List[List[List[int]]],
- List[List[List[int]]],
- List[List[List[Any]]]]:
- r"""
- Translates special_token signifier text in from_tokenizer to to_tokenizer special_token text, for
- a given text_batch. Resulting to_text_batch can then be to_tokenized where special_tokens should
- map to its single corresponding token, despite signifier text difference compared to from_tokenizer.
- Args:
- text_batch (:obj:`List[str]`, `required`):
- List of strings to translate special tokens for.
- from_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- From tokenizer.
- to_tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- To tokenizer.
-
- Returns:
- to_text_batch (:obj:`List[str]`, `required`):
- List of strings where special text has been replaced.
- from_offsets_batch (:obj:`List[List[List[int]]]`, `required`):
- Batch of tokenizer offset mappings selecting replacement tuples in from_tokenizer text
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- to_offsets_batch (:obj:`List[List[List[int]]]`, `required`):
- Batch of tokenizer offset mappings selecting replacement tuples in to_tokenizer text
- [[(left_0, right_0), (left_1, right_1), ...], ...].
- pad_offsets_batch (:obj:`List[List[List[Any]]]`, `required`):
- Batch of offset paddings associated with each replacement tuple
- [[(left_pad_0, right_pad_0), (left_pad_1, right_pad_1), ...], ...].
- """
- to_text_batch = []
- from_offsets_batch = []
- to_offsets_batch = []
- pad_offsets_batch = []
-
- # === Get special-token text replacement pairs ===
- pairings = get_special_token_pairings(from_tokenizer, to_tokenizer)
-
- for text in text_batch:
- from_offsets = []
- padding_offsets = []
- for token_string in pairings:
- offsets = find_offsets(text, token_string) # find special-token locations
- from_offsets += [[left, right, pairings[token_string]] for left, right in offsets]
-
- pad_string = token_string if len(token_string) > len(pairings[token_string]) else pairings[token_string]
- padding_offsets += [[left, right, pad_string] for left, right in offsets]
-
- from_offsets = sorted(from_offsets) # incrementally arrange locations
- to_text, to_offsets = replace_at_offsets(text, from_offsets) # replace special-token text
- pad_text, padding_offsets = replace_at_offsets(text, padding_offsets) # pad special-token text locations
-
- to_text_batch += [to_text]
- from_offsets_batch += [[[left, right] for left, right, _ in from_offsets]]
- to_offsets_batch += [to_offsets]
- pad_offsets_batch += [padding_offsets]
-
- return to_text_batch, from_offsets_batch, to_offsets_batch, pad_offsets_batch
-
-
-def set_vocab_len(tokenizer: PreTrainedTokenizerBase):
- r"""
- Sets the tokenizer.vocab_len if unset, to store the real vocabulary size according to the vocab or encoder.
- Args:
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Tokenizer to set vocab_len for.
- Returns:
-
- """
- if not hasattr(tokenizer, 'vocab_len'):
- if hasattr(tokenizer, 'vocab'): # use independent vocab_len when tokenizer.vocab_size != len(tokenizer.vocab)
- tokenizer.vocab_len = len(tokenizer.vocab)
- elif hasattr(tokenizer, 'encoder'): # tokenizers like facebook/opt-* has encoder=vocab
- tokenizer.vocab_len = len(tokenizer.encoder)
- else: # revert to vocab_size
- tokenizer.vocab_len = tokenizer.vocab_size
-
-
-def set_whitespace_preserving(tokenizer: PreTrainedTokenizerBase):
- r"""
- Sets the tokenizer.whitespace_preserving if unset, indicates if tokenizer preserves whitespace like GPT-style,
- or not like BERT-style.
- Args:
- tokenizer (:obj:`PreTrainedTokenizerBase`, `required`):
- Tokenizer to set vocab_len for.
- Returns:
-
- """
- if not hasattr(tokenizer, 'whitespace_preserving'):
- space_token = tokenizer(' ', add_special_tokens=False)['input_ids']
- space_text = tokenizer.decode(space_token)
- if space_text == ' ':
- tokenizer.whitespace_preserving = True
- else:
- tokenizer.whitespace_preserving = False
-
-
-def set_std_token_phrases(tokenizer, std_tokenizer):
- r"""
- Sets std_token_phrases which are the tokenizer token strings tokenized with std_tokenizer, so
- the std_tokenizer equivalent of the tokenizer token strings.
- Used for converting model predictions/logits into std_tokenizer representations, for example in TextCausalLMNext.
- Args:
- tokenizer(:obj:`PreTrainedTokenizerBase`, `required`):
- Tokenizer to set std_token_phrases for.
- std_tokenizer(:obj:`PreTrainedTokenizerBase`, `required`):
- Standard bittensor tokenizer to convert to.
-
- Returns:
-
- """
- # === Tokenizer phrases to memory ===
- if not hasattr(tokenizer, 'phrases'):
- if tokenizer.whitespace_preserving:
- tokenizer.phrases = tokenizer.batch_decode(range(tokenizer.vocab_len)) # server tokens to strings
- else:
- tokenizer.phrases = [' ' + phrase for phrase in
- tokenizer.batch_decode(range(tokenizer.vocab_len))] # server tokens to strings
-
- if not hasattr(tokenizer, 'std_token_phrases'):
- # Retokenize phrases to new tokenizer
- tokenizer.std_token_phrases = std_tokenizer(tokenizer.phrases)['input_ids'] # [topk, max_len] convert phrases to tokens sequences
-
-
-def prep_tokenizer(tokenizer, std_tokenizer=None):
- tokenizer.padding_side = "left" # Generative default expects most recent token on right-hand side with padding on left. https://github.com/huggingface/transformers/pull/10552
- # tokenizer.add_prefix_space = False
- # tokenizer.add_special_tokens({'bos_token': "[BOS]"}) # A special token representing the beginning of a sentence.
- # tokenizer.add_special_tokens({'eos_token': "[EOS]"}) # A special token representing the end of a sentence.
- # tokenizer.add_special_tokens({'unk_token': "[UNK]"}) # A special token representing an out-of-vocabulary token.
- # tokenizer.add_special_tokens({'sep_token': "[SEP]"}) # A special token separating two different sentences in the same input (used by BERT for instance)
- # tokenizer.add_special_tokens({'pad_token': "[PAD]"}) # A special token used to make arrays of tokens the same size for batching purpose. Will then be ignored by attention mechanisms or loss computation.
- # tokenizer.add_special_tokens({'cls_token': "[CLS]"}) # A special token representing the class of the input (used by BERT for instance).
- # tokenizer.add_special_tokens({'mask_token': "[MASK]"}) # A special token representing a masked token (used by masked-language modeling pretraining objectives, like BERT).
- # additional_special_tokens = [
- # "NOTUSED", # Used by BARThez
- # "NOTUSED", # Used by BARThez
- # "", # Used by MarianMT
- # "", # Used by MarianMT
- # "", # Used by Transformer XL
- # "" # Used by Pegasus
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # "", # Used by XLM
- # ]
- # tokenizer.additional_special_tokens = additional_special_tokens
-
- # Define PAD Token = EOS Token (GPT2 generate convention, when PAD Token is None)
- # https://github.com/huggingface/transformers/blob/49c8c67fb815a277405f84dea4a66353e19fb347/tests/models/gpt2/test_modeling_gpt2.py#L532
- if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None:
- tokenizer.pad_token = tokenizer.eos_token
- set_vocab_len(tokenizer)
- set_whitespace_preserving(tokenizer)
-
- if std_tokenizer is not None:
- set_std_token_phrases(tokenizer, std_tokenizer)
-
- return tokenizer
diff --git a/commune/modules/bittensor/utils/weight_utils.py b/commune/modules/bittensor/utils/weight_utils.py
deleted file mode 100644
index c89d6a9c3..000000000
--- a/commune/modules/bittensor/utils/weight_utils.py
+++ /dev/null
@@ -1,141 +0,0 @@
-""" Conversion for weight between chain representation and torch tensor
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-from typing import Tuple, List
-import torch
-
-U32_MAX = 4294967295
-U16_MAX = 65535
-
-def normalize_max_weight( x: torch.FloatTensor, limit:float = 0.1 ) -> 'torch.FloatTensor':
- r""" Normalizes the tensor x so that sum(x) = 1 and the max value is not greater than the limit.
- Args:
- x (:obj:`torch.FloatTensor`):
- Tensor to be max_value normalized.
- limit: float:
- Max value after normalization.
- Returns:
- y (:obj:`torch.FloatTensor`):
- Normalized x tensor.
- """
- epsilon = 1e-7 #For numerical stability after normalization
-
- weights = x.clone()
- values, _ = torch.sort(weights)
-
- if x.sum() == 0 or len(x)*limit <= 1:
- return torch.ones_like(x)/x.size(0)
- else:
- estimation = values/values.sum()
-
- if estimation.max() <= limit:
- return weights/weights.sum()
-
- # Find the cumlative sum and sorted tensor
- cumsum = torch.cumsum(estimation,0)
-
- # Determine the index of cutoff
- estimation_sum = torch.tensor([(len(values)-i-1)*estimation[i] for i in range(len(values))])
- n_values = (estimation/(estimation_sum+cumsum+epsilon) cutoff] = cutoff
-
- y = weights/weights.sum()
-
- return y
-
-def convert_weight_uids_and_vals_to_tensor( n: int, uids: List[int], weights: List[int] ) -> 'torch.FloatTensor':
- r""" Converts weights and uids from chain representation into a torch tensor (inverse operation from convert_weights_and_uids_for_emit)
- Args:
- n: int:
- number of neurons on network.
- uids (:obj:`List[int],`):
- Tensor of uids as destinations for passed weights.
- weights (:obj:`List[int],`):
- Tensor of weights.
- Returns:
- row_weights ( torch.FloatTensor ):
- Converted row weights.
- """
- row_weights = torch.zeros( [ n ], dtype=torch.float32 )
- for uid_j, wij in list(zip( uids, weights )):
- row_weights[ uid_j ] = float( wij ) / float(U16_MAX)
- return row_weights
-
-def convert_bond_uids_and_vals_to_tensor( n: int, uids: List[int], bonds: List[int] ) -> 'torch.LongTensor':
- r""" Converts bond and uids from chain representation into a torch tensor.
- Args:
- n: int:
- number of neurons on network.
- uids (:obj:`List[int],`):
- Tensor of uids as destinations for passed bonds.
- bonds (:obj:`List[int],`):
- Tensor of bonds.
- Returns:
- row_bonds ( torch.FloatTensor ):
- Converted row bonds.
- """
- row_bonds = torch.zeros( [ n ], dtype=torch.int64 )
- for uid_j, bij in list(zip( uids, bonds )):
- row_bonds[ uid_j ] = int( bij )
- return row_bonds
-
-def convert_weights_and_uids_for_emit( uids: torch.LongTensor, weights: torch.FloatTensor ) -> Tuple[List[int], List[int]]:
- r""" Converts weights into integer u32 representation that sum to MAX_INT_WEIGHT.
- Args:
- uids (:obj:`torch.LongTensor,`):
- Tensor of uids as destinations for passed weights.
- weights (:obj:`torch.FloatTensor,`):
- Tensor of weights.
- Returns:
- weight_uids (List[int]):
- Uids as a list.
- weight_vals (List[int]):
- Weights as a list.
- """
- # Checks.
- weights = weights.tolist()
- uids = uids.tolist()
- if min(weights) < 0:
- raise ValueError('Passed weight is negative cannot exist on chain {}'.format(weights))
- if min(uids) < 0:
- raise ValueError('Passed uid is negative cannot exist on chain {}'.format(uids))
- if len(uids) != len(weights):
- raise ValueError('Passed weights and uids must have the same length, got {} and {}'.format(len(uids), len(weights)))
- if sum(weights) == 0:
- return [],[] # Nothing to set on chain.
- else:
- weights = [ float(value) / sum(weights) for value in weights] # Initial normalization.
-
- weight_vals = []
- weight_uids = []
- for i, (weight_i, uid_i) in enumerate(list(zip(weights, uids))):
- uint16_val = int(float(weight_i) * int(U16_MAX)) # convert to int representation.
-
- # Filter zeros
- if uint16_val != 0: # Filter zeros
- weight_vals.append( uint16_val )
- weight_uids.append( uid_i )
-
- return weight_uids, weight_vals
\ No newline at end of file
diff --git a/commune/modules/bittensor/wallet/__init__.py b/commune/modules/bittensor/wallet/__init__.py
deleted file mode 100644
index 090b7c305..000000000
--- a/commune/modules/bittensor/wallet/__init__.py
+++ /dev/null
@@ -1,149 +0,0 @@
-""" Create and init wallet that stores coldkey and hotkey
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import copy
-from distutils.util import strtobool
-import os
-
-import bittensor
-from bittensor.utils import strtobool
-
-from . import wallet_impl, wallet_mock
-
-
-class wallet:
- """ Create and init wallet that stores hot and coldkey
- """
- @classmethod
- def mock(cls) -> 'bittensor.Wallet':
- return wallet( name='mock' )
-
- def __new__(
- cls,
- config: 'bittensor.Config' = None,
- name: str = None,
- hotkey: str = None,
- path: str = None,
- _mock: bool = None
- ) -> 'bittensor.Wallet':
- r""" Init bittensor wallet object containing a hot and coldkey.
-
- Args:
- config (:obj:`bittensor.Config`, `optional`):
- bittensor.wallet.config()
- name (required=False, default='default'):
- The name of the wallet to unlock for running bittensor
- hotkey (required=False, default='default'):
- The name of hotkey used to running the miner.
- path (required=False, default='~/.bittensor/wallets/'):
- The path to your bittensor wallets
- _mock (required=False, default=False):
- If true creates a mock wallet with random keys.
- """
- if config == None:
- config = wallet.config()
- config = copy.deepcopy( config )
- config.wallet.name = name if name != None else config.wallet.name
- config.wallet.hotkey = hotkey if hotkey != None else config.wallet.hotkey
- config.wallet.path = path if path != None else config.wallet.path
- config.wallet._mock = _mock if _mock != None else config.wallet._mock
- wallet.check_config( config )
- # Allows mocking from the command line.
- if config.wallet.get('name', bittensor.defaults.wallet.name) == 'mock' or config.wallet._mock:
- config.wallet._mock = True
- _mock = True
-
- return wallet_mock.Wallet_mock(
- name = config.wallet.get('name', bittensor.defaults.wallet.name),
- hotkey = config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey),
- path = config.wallet.path,
- _mock = True,
- config = config
- )
-
- return wallet_impl.Wallet(
- name = config.wallet.get('name', bittensor.defaults.wallet.name),
- hotkey = config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey),
- path = config.wallet.path,
- config = config
- )
-
- @classmethod
- def config(cls) -> 'bittensor.Config':
- """ Get config from the argument parser
- Return: bittensor.config object
- """
- parser = argparse.ArgumentParser()
- wallet.add_args( parser )
- return bittensor.config( parser )
-
- @classmethod
- def help(cls):
- """ Print help to stdout
- """
- parser = argparse.ArgumentParser()
- cls.add_args( parser )
- print (cls.__new__.__doc__)
- parser.print_help()
-
- @classmethod
- def add_args(cls, parser: argparse.ArgumentParser, prefix: str = None ):
- """ Accept specific arguments from parser
- """
- prefix_str = '' if prefix == None else prefix + '.'
- try:
- parser.add_argument('--' + prefix_str + 'wallet.name', required=False, default=bittensor.defaults.wallet.name, help='''The name of the wallet to unlock for running bittensor (name mock is reserved for mocking this wallet)''')
- parser.add_argument('--' + prefix_str + 'wallet.hotkey', required=False, default=bittensor.defaults.wallet.hotkey, help='''The name of wallet's hotkey.''')
- parser.add_argument('--' + prefix_str + 'wallet.path', required=False, default=bittensor.defaults.wallet.path, help='''The path to your bittensor wallets''')
- parser.add_argument('--' + prefix_str + 'wallet._mock', action='store_true', default=bittensor.defaults.wallet._mock, help='To turn on wallet mocking for testing purposes.')
-
- parser.add_argument('--' + prefix_str + 'wallet.hotkeys', '--' + prefix_str + 'wallet.exclude_hotkeys', required=False, action='store', default=bittensor.defaults.wallet.hotkeys, type=str, nargs='*', help='''Specify the hotkeys by name. (e.g. hk1 hk2 hk3)''')
- parser.add_argument('--' + prefix_str + 'wallet.all_hotkeys', required=False, action='store_true', default=bittensor.defaults.wallet.all_hotkeys, help='''To specify all hotkeys. Specifying hotkeys will exclude them from this all.''')
- parser.add_argument('--' + prefix_str + 'wallet.reregister', required=False, action='store', default=bittensor.defaults.wallet.reregister, type=strtobool, help='''Whether to reregister the wallet if it is not already registered.''')
-
- except argparse.ArgumentError as e:
- pass
-
- @classmethod
- def add_defaults(cls, defaults):
- """ Adds parser defaults to object from enviroment variables.
- """
- defaults.wallet = bittensor.Config()
- defaults.wallet.name = os.getenv('BT_WALLET_NAME') if os.getenv('BT_WALLET_NAME') != None else 'default'
- defaults.wallet.hotkey = os.getenv('BT_WALLET_HOTKEY') if os.getenv('BT_WALLET_HOTKEY') != None else 'default'
- defaults.wallet.path = os.getenv('BT_WALLET_PATH') if os.getenv('BT_WALLET_PATH') != None else '~/.bittensor/wallets/'
- defaults.wallet._mock = os.getenv('BT_WALLET_MOCK') if os.getenv('BT_WALLET_MOCK') != None else False
- # CLI defaults for Overview
- defaults.wallet.hotkeys = []
- defaults.wallet.all_hotkeys = False
- # Defaults for registration
- defaults.wallet.reregister = True
-
- @classmethod
- def check_config(cls, config: 'bittensor.Config' ):
- """ Check config for wallet name/hotkey/path/hotkeys/sort_by
- """
- assert 'wallet' in config
- assert isinstance(config.wallet.get('name', bittensor.defaults.wallet.name), str)
- assert isinstance(config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey), str ) or config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey) == None
- assert isinstance(config.wallet.path, str)
- assert isinstance(config.wallet.hotkeys, list)
- assert isinstance(config.wallet.reregister, bool)
- assert isinstance(config.wallet.all_hotkeys, bool)
diff --git a/commune/modules/bittensor/wallet/wallet_impl.py b/commune/modules/bittensor/wallet/wallet_impl.py
deleted file mode 100644
index ccb49c46e..000000000
--- a/commune/modules/bittensor/wallet/wallet_impl.py
+++ /dev/null
@@ -1,763 +0,0 @@
-""" Implementation of the wallet class, which manages balances with staking and transfer. Also manages hotkey and coldkey.
-"""
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import os
-import sys
-from types import SimpleNamespace
-from typing import Optional, Union
-
-import bittensor
-from bittensor.utils import is_valid_bittensor_address_or_public_key
-from substrateinterface import Keypair
-from termcolor import colored
-from ..keyfile.keyfile_impl import Keyfile
-
-
-def display_mnemonic_msg( keypair : Keypair, key_type : str ):
- """ Displaying the mnemonic and warning message to keep mnemonic safe
- """
- mnemonic = keypair.mnemonic
- mnemonic_green = colored(mnemonic, 'green')
- print (colored("\nIMPORTANT: Store this mnemonic in a secure (preferable offline place), as anyone " \
- "who has possesion of this mnemonic can use it to regenerate the key and access your tokens. \n", "red"))
- print ("The mnemonic to the new {} is:\n\n{}\n".format(key_type, mnemonic_green))
- print ("You can use the mnemonic to recreate the key in case it gets lost. The command to use to regenerate the key using this mnemonic is:")
- print("btcli regen_{} --mnemonic {}".format(key_type, mnemonic))
- print('')
-
-class Wallet():
- """
- Bittensor wallet maintenance class. Each wallet contains a coldkey and a hotkey.
- The coldkey is the user's primary key for holding stake in their wallet
- and is the only way that users can access Tao. Coldkeys can hold tokens and should be encrypted on your device.
- The coldkey must be used to stake and unstake funds from a running node. The hotkey, on the other hand, is only used
- for suscribing and setting weights from running code. Hotkeys are linked to coldkeys through the metagraph.
- """
- def __init__(
- self,
- name:str,
- path:str,
- hotkey:str,
- config: 'bittensor.Config' = None,
- ):
- r""" Init bittensor wallet object containing a hot and coldkey.
- Args:
- name (required=True, default='default):
- The name of the wallet to unlock for running bittensor
- hotkey (required=True, default='default):
- The name of hotkey used to running the miner.
- path (required=True, default='~/.bittensor/wallets/'):
- The path to your bittensor wallets
- config (:obj:`bittensor.Config`, `optional`):
- bittensor.wallet.config()
- """
- self.name = name
- self.path = path
- self.hotkey_str = hotkey
- self._hotkey = None
- self._coldkey = None
- self._coldkeypub = None
- self.config = config
-
- def __str__(self):
- return "Wallet ({}, {}, {})".format(self.name, self.hotkey_str, self.path)
-
- def __repr__(self):
- return self.__str__()
-
- @property
- def neuron(self) -> SimpleNamespace:
- return self.get_neuron()
-
- @property
- def trust(self) -> SimpleNamespace:
- return self.get_neuron().trust
-
- @property
- def rank(self) -> SimpleNamespace:
- return self.get_neuron().rank
-
- @property
- def incentive(self) -> SimpleNamespace:
- return self.get_neuron().incentive
-
- @property
- def dividends(self) -> SimpleNamespace:
- return self.get_neuron().dividends
-
- @property
- def consensus(self) -> SimpleNamespace:
- return self.get_neuron().consensus
-
- @property
- def inflation(self) -> SimpleNamespace:
- return self.get_neuron().inflation
-
- @property
- def ip(self) -> SimpleNamespace:
- return self.get_neuron().ip
-
- @property
- def last_update(self) -> SimpleNamespace:
- return self.get_neuron().last_update
-
- @property
- def weights(self) -> SimpleNamespace:
- return self.get_neuron().weights
-
- @property
- def bonds(self) -> SimpleNamespace:
- return self.get_neuron().bonds
-
- @property
- def uid(self) -> SimpleNamespace:
- return self.get_uid()
-
- @property
- def stake(self) -> SimpleNamespace:
- return self.get_stake()
-
- @property
- def balance(self) -> SimpleNamespace:
- return self.get_balance()
-
- def is_registered( self, subtensor: 'bittensor.Subtensor' = None ) -> bool:
- """ Returns true if this wallet is registered.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- Determines which network we check for registration.
- Return:
- is_registered (bool):
- Is the wallet registered on the chain.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- return subtensor.is_hotkey_registered( self.hotkey.ss58_address )
-
- def get_neuron ( self, subtensor: 'bittensor.Subtensor' = None ) -> Union[ SimpleNamespace, None] :
- """ Returns this wallet's neuron information from subtensor.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- Return:
- neuron (Union[ SimpleNamespace, None ]):
- neuron account on the chain or None if you are not registered.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- if not self.is_registered(subtensor=subtensor):
- print(colored('This wallet is not registered. Call wallet.register() before this function.','red'))
- return None
- neuron = subtensor.neuron_for_wallet( self )
- return neuron
-
- def get_uid ( self, subtensor: 'bittensor.Subtensor' = None ) -> int:
- """ Returns this wallet's hotkey uid or -1 if the hotkey is not subscribed.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- Return:
- uid (int):
- Network uid or -1 if you are not registered.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- if not self.is_registered(subtensor=subtensor):
- print(colored('This wallet is not registered. Call wallet.register() before this function.','red'))
- return -1
- neuron = self.get_neuron(subtensor = subtensor)
- if neuron.is_null:
- return -1
- else:
- return neuron.uid
-
- def get_stake ( self, subtensor: 'bittensor.Subtensor' = None ) -> 'bittensor.Balance':
- """ Returns this wallet's staking balance from passed subtensor connection.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- Return:
- balance (bittensor.utils.balance.Balance):
- Stake account balance.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- if not self.is_registered(subtensor=subtensor):
- print(colored('This wallet is not registered. Call wallet.register() before this function.','red'))
- return bittensor.Balance(0)
- neuron = self.get_neuron(subtensor = subtensor)
- if neuron.is_null:
- return bittensor.Balance(0)
- else:
- return bittensor.Balance.from_tao(neuron.stake)
-
- def get_balance( self, subtensor: 'bittensor.Subtensor' = None ) -> 'bittensor.Balance':
- """ Returns this wallet's coldkey balance from passed subtensor connection.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- Return:
- balance (bittensor.utils.balance.Balance):
- Coldkey balance.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- return subtensor.get_balance(address = self.coldkeypub.ss58_address)
-
- def reregister(
- self,
- subtensor: 'bittensor.Subtensor' = None,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False
- ) -> Optional['bittensor.Wallet']:
- """ Re-register this wallet on the chain.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
-
- Return:
- wallet (bittensor.Wallet):
- This wallet.
- """
- if subtensor == None:
- subtensor = bittensor.subtensor()
- if not self.is_registered(subtensor=subtensor):
- # Check if the wallet should reregister
- if not self.config.wallet.get('reregister'):
- sys.exit(0)
-
- self.register(
- subtensor = subtensor,
- prompt = prompt,
- TPB = self.config.subtensor.register.cuda.get('TPB', None),
- update_interval = self.config.subtensor.register.cuda.get('update_interval', None),
- num_processes = self.config.subtensor.register.get('num_processes', None),
- cuda = self.config.subtensor.register.cuda.get('use_cuda', bittensor.defaults.subtensor.register.cuda.use_cuda),
- dev_id = self.config.subtensor.register.cuda.get('dev_id', None),
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- output_in_place = self.config.subtensor.register.get('output_in_place', bittensor.defaults.subtensor.register.output_in_place),
- log_verbose = self.config.subtensor.register.get('verbose', bittensor.defaults.subtensor.register.verbose),
- )
-
- return self
-
- def register (
- self,
- subtensor: 'bittensor.Subtensor' = None,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- prompt: bool = False,
- max_allowed_attempts: int = 3,
- cuda: bool = False,
- dev_id: int = 0,
- TPB: int = 256,
- num_processes: Optional[int] = None,
- update_interval: Optional[int] = None,
- output_in_place: bool = True,
- log_verbose: bool = False,
- ) -> 'bittensor.Wallet':
- """ Registers the wallet to chain.
- Args:
- subtensor( 'bittensor.Subtensor' ):
- Bittensor subtensor connection. Overrides with defaults if None.
- wait_for_inclusion (bool):
- If set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- If set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- max_allowed_attempts (int):
- Maximum number of attempts to register the wallet.
- cuda (bool):
- If true, the wallet should be registered on the cuda device.
- dev_id (int):
- The cuda device id.
- TPB (int):
- The number of threads per block (cuda).
- num_processes (int):
- The number of processes to use to register.
- update_interval (int):
- The number of nonces to solve between updates.
- output_in_place (bool):
- If true, the registration output is printed in-place.
- log_verbose (bool):
- If true, the registration output is more verbose.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- # Get chain connection.
- if subtensor == None: subtensor = bittensor.subtensor()
- subtensor.register(
- wallet = self,
- wait_for_inclusion = wait_for_inclusion,
- wait_for_finalization = wait_for_finalization,
- prompt=prompt, max_allowed_attempts=max_allowed_attempts,
- output_in_place = output_in_place,
- cuda=cuda,
- dev_id=dev_id,
- TPB=TPB,
- num_processes=num_processes,
- update_interval=update_interval,
- log_verbose=log_verbose,
- )
-
- return self
-
- def add_stake( self,
- amount: Union[float, bittensor.Balance] = None,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- subtensor: 'bittensor.Subtensor' = None,
- prompt: bool = False
- ) -> bool:
- """ Stakes tokens from this wallet's coldkey onto it's hotkey.
- Args:
- amount_tao (float):
- amount of tao to stake or bittensor balance object. If None, stakes all available balance.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- subtensor( `bittensor.Subtensor` ):
- Bittensor subtensor connection. Overrides with defaults if None.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- return subtensor.add_stake( wallet = self, amount = amount, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization, prompt=prompt )
-
- def remove_stake( self,
- amount: Union[float, bittensor.Balance] = None,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- subtensor: 'bittensor.Subtensor' = None,
- prompt: bool = False,
- ) -> bool:
- """ Removes stake from this wallet's hotkey and moves them onto it's coldkey balance.
- Args:
- amount_tao (float):
- amount of tao to unstake or bittensor balance object. If None, unstakes all available hotkey balance.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- subtensor( `bittensor.Subtensor` ):
- Bittensor subtensor connection. Overrides with defaults if None.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- return subtensor.unstake( wallet = self, amount = amount, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization, prompt=prompt )
-
- def transfer(
- self,
- dest:str,
- amount: Union[float, bittensor.Balance] ,
- wait_for_inclusion: bool = False,
- wait_for_finalization: bool = True,
- subtensor: 'bittensor.Subtensor' = None,
- prompt: bool = False,
- ) -> bool:
- """ Transfers Tao from this wallet's coldkey to the destination address.
- Args:
- dest (`type`:str, required):
- The destination address either encoded as a ss58 or ed255 public-key string of
- secondary account.
- amount (float, required):
- amount of tao to transfer or a bittensor balance object.
- wait_for_inclusion (bool):
- if set, waits for the extrinsic to enter a block before returning true,
- or returns false if the extrinsic fails to enter the block within the timeout.
- wait_for_finalization (bool):
- if set, waits for the extrinsic to be finalized on the chain before returning true,
- or returns false if the extrinsic fails to be finalized within the timeout.
- subtensor( `bittensor.Subtensor` ):
- Bittensor subtensor connection. Overrides with defaults if None.
- prompt (bool):
- If true, the call waits for confirmation from the user before proceeding.
- Returns:
- success (bool):
- flag is true if extrinsic was finalized or uncluded in the block.
- If we did not wait for finalization / inclusion, the response is true.
- """
- if subtensor == None: subtensor = bittensor.subtensor()
- return subtensor.transfer( wallet = self, dest = dest, amount = amount, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization, prompt=prompt )
-
- def create_if_non_existent( self, coldkey_use_password:bool = True, hotkey_use_password:bool = False) -> 'Wallet':
- """ Checks for existing coldkeypub and hotkeys and creates them if non-existent.
- """
- return self.create(coldkey_use_password, hotkey_use_password)
-
- def create (self, coldkey_use_password:bool = True, hotkey_use_password:bool = False ) -> 'Wallet':
- """ Checks for existing coldkeypub and hotkeys and creates them if non-existent.
- """
- # ---- Setup Wallet. ----
- if not self.coldkey_file.exists_on_device() and not self.coldkeypub_file.exists_on_device():
- self.create_new_coldkey( n_words = 12, use_password = coldkey_use_password )
- if not self.hotkey_file.exists_on_device():
- self.create_new_hotkey( n_words = 12, use_password = hotkey_use_password )
- return self
-
- def recreate (self, coldkey_use_password:bool = True, hotkey_use_password:bool = False ) -> 'Wallet':
- """ Checks for existing coldkeypub and hotkeys and creates them if non-existent.
- """
- # ---- Setup Wallet. ----
- self.create_new_coldkey( n_words = 12, use_password = coldkey_use_password )
- self.create_new_hotkey( n_words = 12, use_password = hotkey_use_password )
- return self
-
- @property
- def hotkey_file(self) -> 'Keyfile':
-
- wallet_path = os.path.expanduser(os.path.join(self.path, self.name))
- hotkey_path = os.path.join(wallet_path, "hotkeys", self.hotkey_str)
- return Keyfile( path = hotkey_path )
-
- @property
- def coldkey_file(self) -> 'Keyfile':
- wallet_path = os.path.expanduser(os.path.join(self.path, self.name))
- coldkey_path = os.path.join(wallet_path, "coldkey")
- return Keyfile( path = coldkey_path )
-
- @property
- def coldkeypub_file(self) -> 'Keyfile':
- wallet_path = os.path.expanduser(os.path.join(self.path, self.name))
- coldkeypub_path = os.path.join(wallet_path, "coldkeypub.txt")
- return Keyfile( path = coldkeypub_path )
-
- def set_hotkey(self, keypair: 'bittensor.Keypair', encrypt: bool = False, overwrite: bool = False) -> 'Keyfile':
- self._hotkey = keypair
- self.hotkey_file.set_keypair( keypair, encrypt = encrypt, overwrite = overwrite )
-
- def set_coldkeypub(self, keypair: 'bittensor.Keypair', encrypt: bool = False, overwrite: bool = False) -> 'Keyfile':
- self._coldkeypub = Keypair(ss58_address=keypair.ss58_address)
- self.coldkeypub_file.set_keypair( self._coldkeypub, encrypt = encrypt, overwrite = overwrite )
-
- def set_coldkey(self, keypair: 'bittensor.Keypair', encrypt: bool = True, overwrite: bool = False) -> 'Keyfile':
- self._coldkey = keypair
- self.coldkey_file.set_keypair( self._coldkey, encrypt = encrypt, overwrite = overwrite )
-
- def get_coldkey(self, password: str = None ) -> 'bittensor.Keypair':
- self.coldkey_file.get_keypair( password = password )
-
- def get_hotkey(self, password: str = None ) -> 'bittensor.Keypair':
- self.hotkey_file.get_keypair( password = password )
-
- def get_coldkeypub(self, password: str = None ) -> 'bittensor.Keypair':
- self.coldkeypub_file.get_keypair( password = password )
-
- @property
- def hotkey(self) -> 'bittensor.Keypair':
- r""" Loads the hotkey from wallet.path/wallet.name/hotkeys/wallet.hotkey or raises an error.
- Returns:
- hotkey (Keypair):
- hotkey loaded from config arguments.
- Raises:
- KeyFileError: Raised if the file is corrupt of non-existent.
- CryptoKeyError: Raised if the user enters an incorrec password for an encrypted keyfile.
- """
- if self._hotkey == None:
- self._hotkey = self.hotkey_file.keypair
- return self._hotkey
-
- @property
- def coldkey(self) -> 'bittensor.Keypair':
- r""" Loads the hotkey from wallet.path/wallet.name/coldkey or raises an error.
- Returns:
- coldkey (Keypair):
- colkey loaded from config arguments.
- Raises:
- KeyFileError: Raised if the file is corrupt of non-existent.
- CryptoKeyError: Raised if the user enters an incorrec password for an encrypted keyfile.
- """
- if self._coldkey == None:
- self._coldkey = self.coldkey_file.keypair
- return self._coldkey
-
- @property
- def coldkeypub(self) -> 'bittensor.Keypair':
- r""" Loads the coldkeypub from wallet.path/wallet.name/coldkeypub.txt or raises an error.
- Returns:
- coldkeypub (Keypair):
- colkeypub loaded from config arguments.
- Raises:
- KeyFileError: Raised if the file is corrupt of non-existent.
- CryptoKeyError: Raised if the user enters an incorrect password for an encrypted keyfile.
- """
- if self._coldkeypub == None:
- self._coldkeypub = self.coldkeypub_file.keypair
- return self._coldkeypub
-
- def create_coldkey_from_uri(self, uri:str, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Creates coldkey from suri string, optionally encrypts it with the user's inputed password.
- Args:
- uri: (str, required):
- URI string to use i.e. /Alice or /Bob
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the coldkey under the same path //coldkey
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created coldkey.
- """
- keypair = Keypair.create_from_uri( uri )
- display_mnemonic_msg( keypair, "coldkey" )
- self.set_coldkey( keypair, encrypt = use_password, overwrite = overwrite)
- self.set_coldkeypub( keypair, overwrite = overwrite)
- return self
-
- def create_hotkey_from_uri( self, uri:str, use_password: bool = False, overwrite:bool = False) -> 'Wallet':
- """ Creates hotkey from suri string, optionally encrypts it with the user's inputed password.
- Args:
- uri: (str, required):
- URI string to use i.e. /Alice or /Bob
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the hotkey under the same path //hotkeys/
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created hotkey.
- """
- keypair = Keypair.create_from_uri( uri )
- display_mnemonic_msg( keypair, "hotkey" )
- self.set_hotkey( keypair, encrypt=use_password, overwrite = overwrite)
- return self
-
- def new_coldkey( self, n_words:int = 12, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Creates a new coldkey, optionally encrypts it with the user's inputed password and saves to disk.
- Args:
- n_words: (int, optional):
- Number of mnemonic words to use.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the coldkey under the same path //coldkey
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created coldkey.
- """
- self.create_new_coldkey( n_words, use_password, overwrite )
-
- def create_new_coldkey( self, n_words:int = 12, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Creates a new coldkey, optionally encrypts it with the user's inputed password and saves to disk.
- Args:
- n_words: (int, optional):
- Number of mnemonic words to use.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the coldkey under the same path //coldkey
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created coldkey.
- """
- mnemonic = Keypair.generate_mnemonic( n_words)
- keypair = Keypair.create_from_mnemonic(mnemonic)
- display_mnemonic_msg( keypair, "coldkey" )
- self.set_coldkey( keypair, encrypt = use_password, overwrite = overwrite)
- self.set_coldkeypub( keypair, overwrite = overwrite)
- return self
-
- def new_hotkey( self, n_words:int = 12, use_password: bool = False, overwrite:bool = False) -> 'Wallet':
- """ Creates a new hotkey, optionally encrypts it with the user's inputed password and saves to disk.
- Args:
- n_words: (int, optional):
- Number of mnemonic words to use.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the hotkey under the same path //hotkeys/
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created hotkey.
- """
- self.create_new_hotkey( n_words, use_password, overwrite )
-
- def create_new_hotkey( self, n_words:int = 12, use_password: bool = False, overwrite:bool = False) -> 'Wallet':
- """ Creates a new hotkey, optionally encrypts it with the user's inputed password and saves to disk.
- Args:
- n_words: (int, optional):
- Number of mnemonic words to use.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the hotkey under the same path //hotkeys/
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created hotkey.
- """
- mnemonic = Keypair.generate_mnemonic( n_words)
- keypair = Keypair.create_from_mnemonic(mnemonic)
- display_mnemonic_msg( keypair, "hotkey" )
- self.set_hotkey( keypair, encrypt=use_password, overwrite = overwrite)
- return self
-
- def regen_coldkey( self, mnemonic: Optional[Union[list, str]]=None, seed: Optional[str]=None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Regenerates the coldkey from passed mnemonic, encrypts it with the user's password and save the file
- Args:
- mnemonic: (Union[list, str], optional):
- Key mnemonic as list of words or string space separated words.
- seed: (str, optional):
- Seed as hex string.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the coldkey under the same path //coldkey
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created coldkey.
- """
- self.regenerate_coldkey(mnemonic, seed, use_password, overwrite)
-
- def regenerate_coldkeypub( self, ss58_address: Optional[str] = None, public_key: Optional[Union[str, bytes]] = None, overwrite: bool = False ) -> 'Wallet':
- """ Regenerates the coldkeypub from passed ss58_address or public_key and saves the file
- Requires either ss58_address or public_key to be passed.
- Args:
- ss58_address: (str, optional):
- Address as ss58 string.
- public_key: (str | bytes, optional):
- Public key as hex string or bytes.
- overwrite (bool, optional) (default: False):
- Will this operation overwrite the coldkeypub (if exists) under the same path //coldkeypub
- Returns:
- wallet (bittensor.Wallet):
- newly re-generated Wallet with coldkeypub.
-
- """
- if ss58_address is None and public_key is None:
- raise ValueError("Either ss58_address or public_key must be passed")
-
- if not is_valid_bittensor_address_or_public_key( ss58_address if ss58_address is not None else public_key ):
- raise ValueError(f"Invalid {'ss58_address' if ss58_address is not None else 'public_key'}")
-
- keypair = Keypair(ss58_address=ss58_address, public_key=public_key, ss58_format=bittensor.__ss58_format__)
-
- # No need to encrypt the public key
- self.set_coldkeypub( keypair, overwrite = overwrite)
-
- return self
-
- # Short name for regenerate_coldkeypub
- regen_coldkeypub = regenerate_coldkeypub
-
- def regenerate_coldkey( self, mnemonic: Optional[Union[list, str]] = None, seed: Optional[str] = None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Regenerates the coldkey from passed mnemonic, encrypts it with the user's password and save the file
- Args:
- mnemonic: (Union[list, str], optional):
- Key mnemonic as list of words or string space separated words.
- seed: (str, optional):
- Seed as hex string.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the coldkey under the same path //coldkey
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created coldkey.
- """
- if mnemonic is None and seed is None:
- raise ValueError("Must pass either mnemonic or seed")
- if mnemonic is not None:
- if isinstance( mnemonic, str): mnemonic = mnemonic.split()
- if len(mnemonic) not in [12,15,18,21,24]:
- raise ValueError("Mnemonic has invalid size. This should be 12,15,18,21 or 24 words")
- keypair = Keypair.create_from_mnemonic(" ".join(mnemonic))
- display_mnemonic_msg( keypair, "coldkey" )
- else:
- # seed is not None
- keypair = Keypair.create_from_seed(seed)
-
- self.set_coldkey( keypair, encrypt = use_password, overwrite = overwrite)
- self.set_coldkeypub( keypair, overwrite = overwrite)
- return self
-
- def regen_hotkey( self, mnemonic: Optional[Union[list, str]], seed: Optional[str] = None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Regenerates the hotkey from passed mnemonic, encrypts it with the user's password and save the file
- Args:
- mnemonic: (Union[list, str], optional):
- Key mnemonic as list of words or string space separated words.
- seed: (str, optional):
- Seed as hex string.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the hotkey under the same path //hotkeys/
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created hotkey.
- """
- self.regenerate_hotkey(mnemonic, seed, use_password, overwrite)
-
- def regenerate_hotkey( self, mnemonic: Optional[Union[list, str]] = None, seed: Optional[str] = None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
- """ Regenerates the hotkey from passed mnemonic, encrypts it with the user's password and save the file
- Args:
- mnemonic: (Union[list, str], optional):
- Key mnemonic as list of words or string space separated words.
- seed: (str, optional):
- Seed as hex string.
- use_password (bool, optional):
- Is the created key password protected.
- overwrite (bool, optional):
- Will this operation overwrite the hotkey under the same path //hotkeys/
- Returns:
- wallet (bittensor.Wallet):
- this object with newly created hotkey.
- """
- if mnemonic is None and seed is None:
- raise ValueError("Must pass either mnemonic or seed")
- if mnemonic is not None:
- if isinstance( mnemonic, str): mnemonic = mnemonic.split()
- if len(mnemonic) not in [12,15,18,21,24]:
- raise ValueError("Mnemonic has invalid size. This should be 12,15,18,21 or 24 words")
- keypair = Keypair.create_from_mnemonic(" ".join(mnemonic))
- display_mnemonic_msg( keypair, "hotkey" )
- else:
- # seed is not None
- keypair = Keypair.create_from_seed(seed)
-
- self.set_hotkey( keypair, encrypt=use_password, overwrite = overwrite)
- return self
-
- @classmethod
- def sand(cls):
- c.print(cls.get_wallet('ensemble.1').__dict__)
diff --git a/commune/modules/bittensor/wallet/wallet_mock.py b/commune/modules/bittensor/wallet/wallet_mock.py
deleted file mode 100644
index 51985d6ba..000000000
--- a/commune/modules/bittensor/wallet/wallet_mock.py
+++ /dev/null
@@ -1,59 +0,0 @@
-
-from . import wallet_impl
-import os
-import bittensor
-
-class Wallet_mock(wallet_impl.Wallet):
- """
- Mocked Version of the bittensor wallet class, meant to be used for testing
- """
- def __init__(
- self,
- _mock:bool,
- **kwargs,
- ):
- r""" Init bittensor wallet object containing a hot and coldkey.
- Args:
- _mock (required=True, default=False):
- If true creates a mock wallet with random keys.
- """
- super().__init__(**kwargs)
- # For mocking.
- self._is_mock = _mock
- self._mocked_coldkey_keyfile = None
- self._mocked_hotkey_keyfile = None
-
- print("---- MOCKED WALLET INITIALIZED- ---")
-
- @property
- def hotkey_file(self) -> 'bittensor.Keyfile':
- if self._is_mock:
- if self._mocked_hotkey_keyfile == None:
- self._mocked_hotkey_keyfile = bittensor.keyfile(path='MockedHotkey', _mock = True)
- return self._mocked_hotkey_keyfile
- else:
- wallet_path = os.path.expanduser(os.path.join(self.path, self.name))
- hotkey_path = os.path.join(wallet_path, "hotkeys", self.hotkey_str)
- return bittensor.keyfile( path = hotkey_path )
-
- @property
- def coldkey_file(self) -> 'bittensor.Keyfile':
- if self._is_mock:
- if self._mocked_coldkey_keyfile == None:
- self._mocked_coldkey_keyfile = bittensor.keyfile(path='MockedColdkey', _mock = True)
- return self._mocked_coldkey_keyfile
- else:
- wallet_path = os.path.expanduser(os.path.join(self.path, self.name))
- coldkey_path = os.path.join(wallet_path, "coldkey")
- return bittensor.keyfile( path = coldkey_path )
-
- @property
- def coldkeypub_file(self) -> 'bittensor.Keyfile':
- if self._is_mock:
- if self._mocked_coldkey_keyfile == None:
- self._mocked_coldkey_keyfile = bittensor.keyfile(path='MockedColdkeyPub', _mock = True)
- return self._mocked_coldkey_keyfile
- else:
- wallet_path = os.path.expanduser(os.path.join(self.path, self.name))
- coldkeypub_path = os.path.join(wallet_path, "coldkeypub.txt")
- return bittensor.Keyfile( path = coldkeypub_path )
\ No newline at end of file
diff --git a/commune/modules/cli/__init__.py b/commune/modules/cli/__init__.py
deleted file mode 100644
index 3d650e79b..000000000
--- a/commune/modules/cli/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-
-from .cli import CLI as cli
-
-if __name__ == '__main__':
- import sys
- args = sys.argv[1:]
- cli(args)
diff --git a/commune/modules/cli/__main__.py b/commune/modules/cli/__main__.py
deleted file mode 100644
index 47b0c480b..000000000
--- a/commune/modules/cli/__main__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-
-from commune.cli import cli
-
-import sys
-args = sys.argv[1:]
-cli(args)
diff --git a/commune/modules/cli/cli.py b/commune/modules/cli/cli.py
deleted file mode 100644
index 8362ae66c..000000000
--- a/commune/modules/cli/cli.py
+++ /dev/null
@@ -1,94 +0,0 @@
-
-import warnings
-warnings.filterwarnings("ignore")
-import commune as c
-
-class CLI(c.Module):
- """
- Create and init the CLI class, which handles the coldkey, hotkey and tao transfer
- """
- #
- def __init__(
- self,
- config: c.Config = None,
- module_overrides: dict = ['network', 'key'],
-
- ) :
- c.new_event_loop(True)
- self.module = c.Module()
- args, kwargs = self.parse_args()
-
- module_list = c.modules()
-
- fn = None
- module = None
- if len(args) == 0:
- result = c.schema()
- elif len(args)> 0:
- functions = list(set(self.module.functions() + self.module.get_attributes()))
- args[0] = self.resolve_shortcut(args[0])
-
- # is it a fucntion, assume it is for the module
-
- module_list = c.modules()
- if args[0] in functions and args[0] not in module_overrides:
- # is a function
- module = c.Module
- fn = args.pop(0)
- elif args[0] in module_list:
- # is a module
- module = args.pop(0)
- module = c.module(module)
-
- else:
- # is a a namespace
- namespace = self.namespace(update=False)
- if args[0] in namespace:
- module = args.pop(0)
- module = c.connect(module)
-
- else:
- raise Exception(f'No module, function or server found for {args[0]}')
-
- if fn == None:
- if len(args) == 0:
- fn = "__init__"
- else:
- fn = args.pop(0)
-
-
- if fn != '__init__':
- fn_name = fn
- fn = getattr(module, fn_name)
-
-
- # if c.is_property(fn):
- # result = getattr(module(), fn.__name__)
-
- if callable(fn) :
- if c.classify_method(fn) == 'self':
- module_inst = module()
- fn = getattr(module_inst, fn_name)
- elif c.is_property(fn):
- result = getattr(module(), fn_name)
- else:
- result = fn
-
- else:
- fn = module
-
-
- if callable(fn):
- result = fn(*args, **kwargs)
-
- else:
- raise Exception ('No module, function or server found for {args[0]}')
-
- if isinstance(result, type(None)):
- c.print(result)
- else:
- if c.is_generator(result):
- for i in result:
- c.print(i)
- else:
- c.print(result)
\ No newline at end of file
diff --git a/commune/modules/client/__init__.py b/commune/modules/client/__init__.py
deleted file mode 100755
index 8b1378917..000000000
--- a/commune/modules/client/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/commune/modules/client/estuary/__init__.py b/commune/modules/client/estuary/__init__.py
deleted file mode 100755
index 4178abae8..000000000
--- a/commune/modules/client/estuary/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .estuary import EstuaryModule
\ No newline at end of file
diff --git a/commune/modules/client/estuary/estuary.py b/commune/modules/client/estuary/estuary.py
deleted file mode 100755
index 9fafb11af..000000000
--- a/commune/modules/client/estuary/estuary.py
+++ /dev/null
@@ -1,919 +0,0 @@
-import fsspec
-import os
-from fsspec import register_implementation
-import asyncio
-import json
-import pickle
-import io
-from datasets import load_dataset, Dataset
-import os, sys
-
-import requests
-
-from commune.client.local import LocalModule
-from commune.client.ipfs import IPFSModule
-from commune import Module
-from commune.utils.function import try_n_times
-
-
-# %% ../nbs/00_utils.ipynb 5
-def parse_response(
- response, # Response object
-):
- "Parse response object into JSON"
-
- if response.text.split('\n')[-1] == "":
- try:
- return [json.loads(each) for each in response.text.split('\n')[:-1]]
-
- except:
- pass
-
- try:
- return response.json()
-
- except:
- return response.text
-
-# register_implementation(IPFSFileSystem.protocol, IPFSFileSystem)
-# register_implementation(AsyncIPFSFileSystem.protocol, AsyncIPFSFileSystem)
-
-
-class EstuaryModule(Module):
-
- def __init__(self, config=None):
- Module.__init__(self, config=config)
- self.api_key = self.get_api_key(api_key = self.config.get('api_key'))
- self.local = LocalModule()
- self.ipfs = IPFSModule()
- self.url = self.config.get('url', 'https://shuttle-4.estuary.tech')
-
- def get_api_key(self, api_key=None):
- if api_key == None:
- api_key = self.config.get('api_key')
- api_key =os.getenv(api_key, api_key)
- if api_key != None:
- # if the api_key is a env variable
- return api_key
- else:
- # if the api key is just a key itself (raw)
- assert isinstance(api_key, str)
- return env_api_key
-
-
- def est_get_viewer(
- api_key: str=None # Your Estuary API key
- ):
-
- api_key = self.resolve_api_key(api_key)
- "View your Estuary account details"
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/viewer', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 6
- # list pins
- def list_pins(self,
- api_key: str=None # Your Estuary API key
- ):
- "List all your pins"
-
- api_key = self.resolve_api_key(api_key)
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/pinning/pins', headers=headers)
- return self.handle_response(response, return_fn=lambda x: x['results'] )
-
-
- ls_pins = list_pins
-
- # %% ../nbs/02_estuaryapi.ipynb 7
- # add pin
-
-
- def rm_all_pins(self):
-
- pins = self.list_pins()[1][0]['results']
- return [self.remove_pin(p['requestid']) for p in pins]
-
- def add_pin(self,
- file_name: str, # File name to pin
- cid: str, # CID to attach
- api_key: str=None # Your Estuary API key
-
- ):
- "Add a new pin object for the current access token."
- api_key = self.resolve_api_key(api_key)
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- json_data = {
- 'name': name,
- 'cid': cid,
- }
-
- response = requests.post(f'{self.url["post"]}/pinning/pins', headers=headers, json=json_data)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 8
- # get pin by ID
- def get_pin(self,
- pin_id: str, # Unique pin ID
- api_key: str=None # Your Estuary API key
-
- ):
- "Get a pinned object by ID"
- api_key = self.resolve_api_key(api_key)
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/pinning/pins/{pin_id}', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 9
- # replace pin by ID
- def replace_pin(self,
- pin_id: str, # Unique pin ID
- api_key: str=None # Your Estuary API key
-
- ):
- api_key = self.resolve_api_key(api_key)
- "Replace a pinned object by ID"
-
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.post(f'{self.url["post"]}/pinning/pins/{pin_id}', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 10
- # remove pin by ID
- def remove_pin(self,
- pin_id: str, # Unique pin ID
- api_key: str=None # Your Estuary API key
-
- ):
- "Remove a pinned object by ID"
- api_key = self.resolve_api_key(api_key)
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.delete(f'{self.url["get"]}/pinning/pins/{pin_id}', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 12
- # create new collection
- def create_collection(self,
- name: str, # Collection name
- description: str='No Description', # Collection description
- handle_error:bool=True,
- api_key: str= None # Your Estuary API key
-
-
- ):
-
- collection = self.get_collection(name)
- if collection !=None:
- return collection
- "Create new collection"
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- json_data = {
- 'name': name,
- 'description': description,
- }
-
- response = requests.post(f'{self.url["get"]}/collections/create', headers=headers, json=json_data)
- return self.handle_response(response)
-
- add_collection = create_collection
- def rm_collection(self,
- collection: str, # Collection name
- api_key: str= None # Your Estuary API key
-
- ):
-
- "Create new collection"
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- collection = self.get_collection(collection)
- if collection == None:
- return None
-
- assert isinstance(collection, dict)
- uuid = collection['uuid']
-
- response = requests.delete(f'{self.url["get"]}/collections/{uuid}', headers=headers)
- return self.handle_response(response)
-
- delete_collection = remove_collection = rm_collection
-
-
- # %% ../nbs/02_estuaryapi.ipynb 13
- # add content
-
- @property
- def name2collection(self):
- return {c['name']:c for c in self.list_collections()}
-
- @property
- def uuid2collection(self):
- return {c['uuid']:c for c in self.list_collections()}
-
-
- def collection_exists(self, collection):
- return bool(self.get_collection(collection))
-
- def get_collection(self, collection:str, handle_error=True, create_if_null=False):
- # get collection by name
- collection_maps = [self.uuid2collection, self.name2collection]
-
- for collection_map in collection_maps:
- if collection in collection_map:
- return collection_map[collection]
-
-
- if create_if_null:
- return self.create_collection(collection)
- if handle_error:
- return None
- else:
- raise Exception(f'{collection} does not exist in {list(collection_maps[0].keys())} uuids or {list(collection_maps[1].keys())} name')
-
- def add_content(self,
- collection_id: str, # Collection ID
- data: list, # List of paths to data to be added
- cids: list, # List of respective CIDs
- api_key: str= None, # Your Estuary API key
-
- ):
- "Add data to Collection"
-
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- json_data = {
- 'contents': data,
- 'cids': cids,
- 'collection': collection_id,
- }
-
- response = requests.post(f'{self.url["post"]}/collections/add-content', headers=headers, json=json_data)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 14
- # list collections
-
- def list_collections(self,
- api_key: str=None # Your Estuary API key
- ):
- "List your collections"
-
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/collections/list', headers=headers)
-
-
-
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 15
- # list collection content
- def list_collection_content(self,
- collection_id: str, # Collection ID
- api_key: str=None # Your Estuary API key
-
-
- ):
- api_key = self.resolve_api_key(api_key)
-
- "List contents of a collection from ID"
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/collections/content/{collection_id}', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 16
- # FS list content of a path
- def list_content_path(self,
- path: str='/dir1', # Path in collection to list files from
- collection: str='default', # Collection ID
- api_key: str=None # Your Estuary API key
- ):
- "List content of a path in collection"
-
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- collection_id = self.get_collection(collection)['uuid']
-
- params = {
- 'col': collection_id,
- 'dir': path
- }
-
- response = requests.get(f'{self.url["get"]}/collections/fs/list', params=params, headers=headers)
- return response
-
- # %% ../nbs/02_estuaryapi.ipynb 17
- # FS add content to path
- def add_content_path(self,
- collection_id: str, # Collection ID
- path: str, # Path in collection to add files to
- api_key: str=None # Your Estuary API key
-
- ):
- "Add content to a specific file system path in an IPFS collection"
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- params = {
- 'col': collection_id,
- }
-
- response = requests.post(f'{self.url["post"]}/collections/fs/add?col=UUID&content=LOCAL_ID&path={path}', params=params, headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 19
- # add client safe upload key
- def add_key(self,
- api_key:str, # Your Estuary API key
- expiry:str='24h' # Expiry of upload key
- ):
- "Add client safe upload key"
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- 'Accept': 'application/json',
- }
-
- params = {
- 'perms': 'upload',
- 'expiry': expiry,
- }
-
- response = requests.post(f'{self.url["post"]}/user/api-keys', params=params, headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 20
-
- def add_files(self, paths:list, api_key:str=None):
- api_key = self.resolve_api_key(api_key)
-
- file2cid = {}
- for path in paths:
- assert isinstance(path, str)
- assert self.local.isfile(path_to_file)
- file2cid[file] = self.local.add_file(path)
- return file2cid
-
- def add_glob(self, path:str, api_key:str=None, return_type='dict'):
- api_key = self.resolve_api_key(api_key)
- file2cid = {}
-
- for path in self.local.glob(path):
- if self.local.isfile(path):
- #TODO: add asyncio or multi threading for call as it is IO bound
- file2cid[path] = self.add_file(path, return_cid= True)
-
- if return_type == 'dict':
- return file2cid
- elif return_type == 'list':
- return list(file2cid.values())
- else:
- raise NotImplementedError(f'only list and dict is supported but you did {return_type}')
- def add(self, path:str, api_key:str=None):
- if self.local.isdir(path):
- return self.add_dir(path=path, api_key=api_key)
- elif self.local.isfile(path):
- return self.add_file(path=path, api_key=api_key)
-
-
- def add_dir(self, path:str,api_key:str=None, **kwargs):
- assert self.local.isdir(path), path
- return self.add_glob(path=path+'/**', **kwargs)
-
- def add_file(self,
- path: str, # Path to file you want to upload
- api_key: str=None, # Your Estuary API key
- return_cid: bool = False
- ):
- "Upload file to Estuary"
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- 'Accept': 'application/json',
- }
-
- files = {
- 'data': open(path, 'rb'),
- }
-
- response = requests.post(f'{self.url["post"]}/content/add', headers=headers, files=files)
- response = self.handle_response(response)
-
- if return_cid:
- return response['cid']
-
-
- if isinstance(response,dict):
- response['file'] = os.path.basename(path)
- response['size'] = self.ipfs.size(response['cid'])
- return response
- else:
- return response
-
- add_data = add_file
- # %% ../nbs/02_estuaryapi.ipynb 21
- # add CID
- def add_collection_cid(self,
- cid: str, # CID for file,
- path: str, # File name to add to CID
- collection:str='default',
- api_key: str=None, # Your Estuary API key
-
- ):
- "Use an existing IPFS CID to make storage deals."
- api_key = self.resolve_api_key(api_key)
-
- self.create_collection(collection)['uuid']
-
- headers = {
- 'Content-Type': 'application/json',
- 'Authorization': f'Bearer {api_key}',
- }
-
- coluid= self.get_collection(collection)['uuid']
-
-
-
- file_name = os.path.basename(path)
-
- json_data = {
- 'name': file_name,
- 'root': cid,
- 'coluid': coluid,
- 'collectionPath': path
- }
-
- response = requests.post(f'{self.url["get"]}/content/add-ipfs', headers=headers, json=json_data)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 22
- # add CAR
- def add_car(self,
- path: str, # Path to file to store
- api_key: str=None, # Your Estuary API key
- ):
- "Write a Content-Addressable Archive (CAR) file, and make storage deals for its contents."
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- 'Accept': 'application/json',
- }
- api_key = self.resolve_api_key(api_key)
-
-
- with open(path, 'rb') as f:
- data = f.read()
-
- response = requests.post(f'{self.url["post"]}/content/add-car', headers=headers, data=data)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 23
- # make deal with specific provider
- def make_deal(self,
- content_id: str, # Content ID on Estuary
- provider_id: str, # Provider ID
- api_key: str=None # Your Estuary API key
-
- ):
- api_key = self.resolve_api_key(api_key)
-
- "Make a deal with a storage provider and a file you have already uploaded to Estuary"
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- json_data = {
- 'content': content_id,
- }
-
- response = requests.post(f'{self.url["post"]}/deals/make/{provider_id}', headers=headers, json=json_data)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 24
- # data by CID
- def view_data_cid(self,
- cid: str, # CID
- api_key: str=None, # Your Estuary API key
-
- ):
- "View CID information"
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/content/by-cid/{cid}', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 25
- # list data
- def list_data(self,
- api_key: str=None # Your Estuary API key
- ):
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/content/stats', headers=headers)
- return self.handle_response(response)
-
- # list deals
- def list_deals( self,
- api_key: str=None # Your Estuary API key
- ):
- # list deals
- api_key = self.resolve_api_key(api_key)
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/content/deals', headers=headers)
- return self.handle_response(response)
-
- # get deal status by id
-
- def resolve_api_key(self, api_key):
- if api_key == None:
- api_key = self.api_key
- assert isinstance(api_key, str)
- return api_key
-
-
- def get_deal_status(self,
- deal_id: str, # Deal ID,
- ):
- "Get deal status by id"
-
- headers = {
- 'Authorization': f'Bearer {api_key}',
- }
-
- response = requests.get(f'{self.url["get"]}/content/status/{deal_id}', headers=headers)
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 28
- # get Estuary node stats
- def get_node_stats(self):
- "Get Estuary node stats"
-
- response = requests.get(f'{self.url["get"]}/public/stats')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 29
- # get on chain deal data
- def get_deal_data(self):
- "Get on-chain deal data"
-
- response = requests.get(f'{self.url["get"]}/public/metrics/deals-on-chain')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 30
- # get miner query ask
-
- def get_miner_ask(self,
- miner_id: str # Miner ID
- ):
- "Get the query ask and verified ask for any miner"
-
- response = requests.get(f'{self.url["get"]}/public/miners/storage/query/{miner_id}')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 31
- # get failure logs by provider
- def get_failure_logs(self,
- miner_id: str # Miner ID
- ):
- "Get all of the failure logs for a specific miner"
-
- response = requests.get(f'{self.url["get"]}/public/miners/failures/{miner_id}')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 32
- # get deal logs by provider
- def get_deal_logs(self,
- provider_id: str # Provider ID
- ):
- "Get deal logs by provider"
-
- response = requests.get(f'{self.url["get"]}/public/miners/deals/{provider_id}')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 33
- # get provider stats
- def get_provider_stats(self,
- provider_id: str # Provider ID
- ):
- "Get provider stats"
-
- response = requests.get(f'{self.url["get"]}/public/miners/stats/{provider_id}')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 34
- # list providers
- def list_providers(self):
- "List Estuary providers"
-
- response = requests.get(f'{self.url["get"]}/public/miners')
- return self.handle_response(response)
-
- # %% ../nbs/02_estuaryapi.ipynb 36
-
- def get_data(self,
- cid: str, # Data CID
- path_name: str # Path and filename to store the file at
- ):
- "Download data from Estuary CID"
-
- url = f'{self.url["dweb"]}/{cid}'
- response = requests.get(url, allow_redirects=True) # to get content
- with open(path_name, 'wb') as f:
- f.write(response.content)
- return self.handle_response(response)
-
-
-
-
- @property
- def tmp_root_path(self):
- return f'/tmp/commune/{self.id}'
-
- def get_temp_path(self, path='get_temp_path'):
- tmp_path = os.path.join(self.tmp_root_path, path)
- if not os.path.exists(self.tmp_root_path):
- self.local.makedirs(os.path.dirname(path), exist_ok=True)
-
- return tmp_path
-
-
- def save_model(self, model, path:str=None):
-
-
- # self.mkdir(path, create_parents=True)
-
- tmp_path = self.get_temp_path(path=path)
- model.save_pretrained(tmp_path)
- self.mkdirs(path)
-
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path, recursive=True)
-
- return cid
-
- def save_tokenizer(self, tokenizer, path:str='tmp'):
-
-
- # self.mkdir(path, create_parents=True)
-
- tmp_path = self.get_temp_path(path=path)
- tokenizer.save_pretrained(tmp_path)
- self.mkdirs(path)
-
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path, recursive=True)
-
- return cid
-
- def load_tokenizer(self, path:str='tmp'):
- tmp_path = self.get_temp_path(path=path)
- self.get(lpath=tmp_path, rpath=path )
- model = AutoTokenizer.from_pretrained(tmp_path)
- self.local.rm(tmp_path, recursive=True)
- return model
-
- def load_model(self, path:str='tmp'):
- tmp_path = self.get_temp_path(path=path)
- self.get(lpath=tmp_path, rpath=path )
- model = AutoModel.from_pretrained(tmp_path)
- # self.fs.local.rm(tmp_path, recursive=True)
- return model
-
- def load_dataset(self, path='tmp', mode='huggingface'):
- tmp_path = self.get_temp_path(path=path)
- self.get(lpath=tmp_path, rpath=path )
- if mode in ['huggingface', 'hf', '🤗']:
- dataset = Dataset.load_from_disk(tmp_path)
- return dataset
- # self.fs.local.rm(tmp_path, recursive=True)
- elif mode in ['activeloop', 'al']:
- raise NotImplementedError
-
-
-
- supported_dataset_modes = [
- 'huggingface'
- 'activeloop'
- ]
-
- def save_dataset(self, dataset=None, mode='🤗', return_type='dict', **kwargs):
-
- tmp_path = self.get_temp_path()
- self.local.makedirs(tmp_path, True)
-
- if mode in ['huggingface', 'hf', '🤗']:
- if dataset == None:
- load_dataset_kwargs = {}
-
- for k in ['path', 'name', 'split']:
- v= kwargs.get(k)
- assert isinstance(v, str), f'{k} is {v} but should be a string'
- load_dataset_kwargs[k] = v
- dataset = load_dataset(**load_dataset_kwargs)
- dataset = dataset.save_to_disk(tmp_path)
-
- elif mode == 'activeloop':
- if dataset == None:
- path = kwargs.get('path')
- else:
- raise NotImplementedError
-
- return self.add(path=tmp_path)
-
-
-
- def put_json(self, data, path='json_placeholder.pkl'):
- tmp_path = self.get_temp_path(path=path)
- self.local.put_json(path=tmp_path, data=data)
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path)
- return cid
-
- def put_pickle(self, data, path='/pickle_placeholder.pkl'):
- tmp_path = self.get_temp_path(path=path)
- self.local.put_pickle(path=tmp_path, data=data)
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path)
- return cid
-
- def get_pickle(self, path):
- return pickle.loads(self.cat(path))
-
- def get_json(self, path):
- return json.loads(self.cat(path))
-
-
-
- def save(self, lpath, rpath, max_trials=10):
- trial_count = 0
- cid = None
- while trial_count 'aiohttp.Response':
-
- '''
- async api post
-
- Args:
- url (str):
- url of endpoint.
- return_json (bool):
- Return repsonse as json.
- content_type (str):
- Content type of request.
- chunk_size (int):
- Chunk size of streaming endpoint.
- num_chunks (int):
- Number of chunks to stream.
- Returns (aiohttp.Response)
- '''
-
-
- url = os.path.join(self.ipfs_url['post'],'api/v0', endpoint)
-
-
- return_result = None
- # we need to set the
- timeout = aiohttp.ClientTimeout(sock_connect=10, sock_read=10)
- async with aiohttp.ClientSession( timeout=timeout) as session:
- async with session.post(url,params=params,headers=headers, data=data) as res:
- if return_json:
- return_result = await res.json(content_type=content_type)
- else:
- return_result = res
-
- # if num_chunks != None
- if num_chunks:
- return_result = b''
- async for data in res.content.iter_chunked(chunk_size):
- return_result += data
- num_chunks-= 1
- if num_chunks == 0:
- break
- return return_result
-
- async def async_api_get(self,
- endpoint:str,
- return_json:bool = True,
- content_type:str=None,
- chunk_size:int=-1,
- num_chunks:int=1,
- params: dict={},
- headers: dict={},
- **kwargs) -> 'aiohttp.Response':
- '''
- async api post
-
- Args:
- url (str):
- url of endpoint.
- return_json (bool):
- Return repsonse as json.
- content_type (str):
- Content type of request.
- chunk_size (int):
- Chunk size of streaming endpoint.
- num_chunks (int):
- Number of chunks to stream.
- Returns (aiohttp.Response)
- '''
-
- url = os.path.join(self.ipfs_url['get'],'api/v0', endpoint)
-
- return_result = None
- async with aiohttp.ClientSession(loop=self.loop) as session:
- async with session.get(url,params=params,headers=headers) as res:
- if return_json:
- return_result = await res.json(content_type=content_type)
- else:
- return_result = res
-
- if chunk_size:
- return_result = b''
- async for data in res.content.iter_chunked(chunk_size):
- return_result += data
- num_chunks-= 1
- if num_chunks == 0:
- break
- return return_result
-
- async def async_version(self, session):
- res = await self.async_api_get("version")
- return rest
-
-
- def resolve_absolute_path(self, path, include_root=True):
- if include_root:
- if path[:len(os.getenv('PWD'))] != os.getenv('PWD'):
- path = os.getenv('PWD')+'/' + path
-
- return path
-
-
- async def async_get(self, cid:str, output_path:str=None,*args, **kwargs):
- '''
- arg [string]: The path to the IPFS object(s) to be outputted. Required: yes.
- output [string]: The path where the output should be stored. Required: no.
- archive [bool]: Output a TAR archive. Required: no.
- compress [bool]: Compress the output with GZIP compression. Required: no.
- compression-level [int]: The level of compression (1-9). Required: no.
- progress [bool]: Stream progress data. Default: true. Required: no.
-
- '''
- params = dict(arg=cid, **kwargs)
- if isinstance(output_path, str):
- params['output'] = output_path
- res = await self.async_api_get('get', params=params , return_json=False)
- return res
-
-
- async def async_pin(self, session, cid, recursive=False, progress=False, **kwargs):
- kwargs['params'] = kwargs.get('params', {})
- kwargs['params'] = dict(arg=cid, recursive= recursive,progress= progress)
- res = await self.async_api_post(endpoint='pin/add', arg=cid, recursive= recursive, **kwargs)
- return bool(cid in pinned_cid_list)
-
-
-
- async def async_add(self,
- path,
- pin=True,
- chunker=262144 , include_root=True):
- path = self.resolve_absolute_path(path, include_root=include_root)
- self.path2hash = await self.async_load_path2hash()
- file_paths=[]
- assert os.path.exists(path), f'{path} does not exist'
- if os.path.isdir(path):
- # if the path is a directory
- # ensure that / is at the end of the directory
- if path[-1] != '/':
- path += '/'
- glob_pattern = path+'**'
- file_paths = glob(glob_pattern, recursive=True)
- elif os.path.isfile(path):
- file_paths = [path]
-
-
-
- file_paths = list(filter(os.path.isfile, file_paths))
-
- assert len(file_paths) > 0
-
- jobs = asyncio.gather(*[self.async_add_file(path=fp, pin=pin, chunker=chunker) for fp in file_paths])
- responses = await jobs
- path2hash = dict(zip(file_paths,responses))
- self.path2hash.update(path2hash)
- await self.async_save_path2hash()
-
- return dict(zip(file_paths,responses))
-
-
- async def async_rm(self, path):
- await self.async_load_path2hash()
- hash2path = self.hash2path
- file_paths = await self.async_ls(path)
- tasks = []
-
- if path in hash2path:
- tasks = [self.async_pin_rm(cid=path)]
- else:
- for fp in file_paths:
- file_meta = self.path2hash[fp]
- tasks.append(self.async_pin_rm(cid=file_meta['Hash']))
-
- return_jobs = await asyncio.gather(*tasks)
- await self.async_gc()
-
- await self.async_save_path2hash()
- return return_jobs
-
- async def async_pin_ls(self,
- type_:str='all', # The type of pinned keys to list. Can be "direct", "indirect", "recursive", or "all"
- **kwargs,
- ):
- 'List objects pinned to local storage.'
- params = {}
- params['type'] = type_
- params.update(kwargs)
- return await self.async_api_post('pin/ls', params=params)
-
- async def async_gc(self):
-
- response = await self.async_api_post('repo/gc', return_json=False)
- return response
-
- async def async_pin_rm(self,
- cid:str, # Path to object(s) to be unpinned
- recursive:str='true', # Recursively unpin the object linked to by the specified object(s)
- **kwargs,
- ):
- 'List objects pinned to local storage.'
-
- params = {}
- params['arg'] = cid
- params['recursive'] = recursive
- params.update(kwargs)
-
- response = await self.async_api_post('pin/rm', params=params)
- await self.async_load_path2hash()
- return response
-
- async def async_add_file(self,
- path,
- pin=False,
- chunker=262144,
- wrap_with_directory=False,
- ):
-
- path = self.resolve_absolute_path(path)
-
- params = {}
- params['wrap-with-directory'] = 'true' if wrap_with_directory else 'false'
- params['chunker'] = f'size-{chunker}'
- params['pin'] = 'true' if pin else 'false'
- data, headers = stream_files(path, chunk_size=chunker)
-
- async def data_gen_wrapper(data):
- for d in data:
- yield d
-
- data = data_gen_wrapper(data=data)
-
- res = await self.async_api_post(endpoint='add', params=params, data=data, headers=headers)
- return res
- # return res
-
-
- async def async_dag_get(self, **kwargs):
- kwargs['params'] = kwargs.get('params', {})
- kwargs['params'] = dict(arg=cid, recursive= recursive,progress= progress)
- res = await self.async_api_post(endpoint='dag/get', **kwargs)
- return bool(cid in pinned_cid_list)
- async def async_rm_json(self, path=None, recursive=True, **kwargs):
- json_path2hash = self.json_path2hash
- json_hash2path = self.json_hash2path
-
- if path in json_path2hash:
- cid = json_path2hash[path]['Hash']
- cid = await self.async_rm(cid)
- elif path in json_hash2path:
- cid = path
- cid = await self.async_rm(cid)
-
- else:
- path = os.path.join(self.data_dir, path)
- return os.remove(path)
-
- await self.async_load_path2hash()
-
- async def async_save_json(self,
- path:str,
- obj:Union[dict, list],
- include_root:bool=True) -> str:
- """
- Async save of json for storing text hashes
-
- Args:
- path (List[str]):
- Axon to serve.
- obj (bool):
- The object to save locally
- include_root (bool):
- Include self.data_dir as the prefix.
- - if True, ths meants shortens the batch and
- specializes it to be with respect to the dataset's
- root path which is in ./bittensor/dataset
-
- Returns:
- path (str)
- Path of the saved JSON
- """
-
- if os.path.splitext(path)[-1] == '.json':
- path = os.path.splitext(path)[0]
- if include_root:
- path = os.path.join(self.data_dir, path)
- dir_path = os.path.dirname(path)
-
- # ensure the json is the prefix
- if path[-len('.json'):] != '.json':
- path += '.json'
-
- # ensure the directory exists, make otherwise
- if not os.path.isdir(dir_path):
- os.makedirs(dir_path)
-
- assert os.access( dir_path , os.W_OK ), f'dir_path:{dir_path} is not writable'
- with open(path, 'w') as outfile:
- json.dump(obj, outfile)
-
- return path
-
-
- async def async_load_json(self, path:str,include_root:bool=True, default:Union[list, dict]={}) -> Union[list, dict]:
-
- """
- Async save of json for storing text hashes
- Args:
- path (str):
- Path of the loaded json
- include_root (bool):
- Include self.data_dir as the prefix.
- - if True, ths meants shortens the batch and
- specializes it to be with respect to the dataset's
- root path which is in ./bittensor/dataset
- Returns:
- obj (str)
- Object of the saved JSON.
- """
-
- if include_root:
- path = os.path.join(self.data_dir, path)
-
- # Ensure extension.
- dir_path = os.path.dirname(path)
- if os.path.splitext(path)[-1] != '.json':
- path += '.json'
-
- # Ensure dictionary.
- if not os.path.isdir(dir_path):
- os.makedirs(dir_path)
-
- # Load default if file does not exist.
- try:
- with open(path, 'r') as f:
- obj = json.load(f)
- except FileNotFoundError:
- obj = default
- except json.JSONDecodeError:
- obj = default
-
- if isinstance(obj, str):
- obj = json.loads(obj)
- return obj
-
-
- async def async_ls(self, path=''):
- await self.async_load_path2hash()
- path = self.resolve_absolute_path(path)
- path_list = []
- for fp in self.path2hash.keys():
- if fp[:len(path)] == path:
- path_list += [fp]
- return path_list
- async def async_save_path2hash(self):
- pinned_cids = (await self.async_pin_ls()).get('Keys', {}).keys()
- path2hash = {}
- for path, file_meta in self.path2hash.items():
- if file_meta['Hash'] in pinned_cids:
- path2hash[path] = file_meta
-
- await self.async_save_json('path2hash', path2hash )
-
-
- async def async_load_path2hash(self):
- loaded_path2hash = await self.async_load_json('path2hash')
- pinned_cids = (await self.async_pin_ls()).get('Keys', {}).keys()
- path2hash = {}
- for path, file_meta in loaded_path2hash.items():
- if file_meta['Hash'] in pinned_cids:
- path2hash[path] = file_meta
- self.path2hash = path2hash
- return path2hash
-
-
- @property
- def hash2path(self):
- return {file_meta['Hash']: path for path, file_meta in self.path2hash.items()}
-
- @classmethod
- def test_add_rm_file(cls):
- module = cls()
- test_path = 'commune/client/local/module.py'
- module.add(test_path)
- file_paths = module.ls(test_path)
- assert len(file_paths) > 0
- module.rm(test_path)
- file_paths = module.ls(test_path)
- assert len(file_paths) == 0
-
- @classmethod
- def test_add_rm_folder(cls):
- module = cls()
- test_path = 'commune/client/local'
- module.add(test_path)
- file_paths = module.ls(test_path)
- assert len(file_paths) > 0
- module.rm(test_path)
- file_paths = module.ls(test_path)
- assert len(file_paths) == 0
-
- @classmethod
- def test(cls):
- for f in dir(cls):
- if 'test_' in f:
- getattr(cls, f)()
-
-
- ##############
- # ASYNCIO
- ##############
- @staticmethod
- def reset_event_loop(set_loop:bool=True) -> 'asyncio.loop':
- '''
- Reset the event loop
-
- Args:
- set_loop (bool):
- Set event loop if true.
-
- Returns (asyncio.loop)
- '''
- loop = asyncio.new_event_loop()
- if set_loop:
- asyncio.set_event_loop(loop)
- return loop
-
- def set_event_loop(self, loop:'asyncio.loop'=None)-> 'asynco.loop':
- '''
- Set the event loop.
-
- Args:
- loop (asyncio.loop):
- Event loop.
-
- Returns (asyncio.loop)
- '''
-
- if loop == None:
- loop = asyncio.get_event_loop()
- self.loop = loop
- return self.loop
-
- @classmethod
- def test_load_save_json(cls):
- module = cls()
- obj = {'bro': [1]}
- module.save_json('fam',obj )
- assert obj == module.load_json('fam')
-
- json_land_dir = os.path.join(data_dir, 'json_land')
- @property
- def json_path2hash(self):
- path2hash = self.path2hash
- json_path2hash = {}
- for path, file_meta in path2hash.items():
- if self.json_land_dir in path:
- json_path = path.replace(self.json_land_dir, '').split('.')[0]
- if json_path[0] == '/':
- json_path = json_path[1:]
- json_path2hash[json_path] = file_meta
- return json_path2hash
-
- @property
- def json_hash2path(self):
- json_hash2path = {file_meta['Hash']: p for p,file_meta in self.json_path2hash.items()}
- return json_hash2path
-
-
-
-
- async def async_put_json(self,path,input:str):
- path = os.path.join(self.json_land_dir, path)
- path = await self.async_save_json(path,input, include_root=False)
- # Add to path.
- file_meta = await self.async_add(path=path, include_root=False)
- # remove json.
- await self.async_rm_json(path, include_root=False)
-
- return list(file_meta.values())[0]
-
-
-
-
- async def async_get_json(self, path):
- json_path2hash=self.json_path2hash
- if path in json_path2hash:
- cid = json_path2hash[path]['Hash']
- else:
- cid = path
-
- json_bytes = await self.async_cat(cid)
-
- return json.loads(json_bytes)
-
-
- def glob(self, pattern='*', recursive = True):
- return glob(pattern, recursive=recursive)
-
-
-
- async def async_cat(self, cid, offset=0, length=None, **kwargs ):
- '''
- Args:
- offset [int64]: Byte offset to begin reading from. Required: no.
- length [int64]: Maximum number of bytes to read. Required: no.
- progress [bool]: Stream progress data. Default: true. Required: no.
- '''
- return await self.async_api_get('cat', params=dict(arg=cid, **kwargs), return_json=False)
-
- @classmethod
- def test_json(cls):
- module = cls()
- obj = {'fam': [0,2,3]}
- path = 'tmp_path'
- module.put_json(path,obj)
- st.write(obj, module.get_json(path), 'bro')
- assert json.dumps(module.get_json(path)) == json.dumps(obj)
- return obj
-
-
-
- async def async_save_model(self, path:str, model):
-
-
- path_dict = {
- **{f'state_dict.{k}':v for k,v in model.state_dict().items()},
- }
-
- # st.write({k:v.shape for k,v in path_dict.items()})
- task_map = {}
- tasks = []
- for k,v in path_dict.items():
- if k in ['state_dict.embeddings.word_embeddings.weight']:
- continue
- task = self.async_save_json(k,v.tolist())
- st.write(k)
- tasks.append(task)
-
- while len(tasks)>0:
- st.write(tasks)
- finished_tasks, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
- st.write(tasks)
- for finished_task in finished_tasks:
- st.write(task_map[finished_task])
-
-
- @classmethod
- def test_json_rm(cls):
- module = cls()
- obj = {'fam': [0,2,3]}
- path = 'tmp_path'
- module.put_json(path,obj)
- module.rm_json(path,obj)
- loaded_obj = module.get_json(path)
- assert loaded_obj.get('Type') == 'error', loaded_obj
- return obj
-
-# import aiofile
-if __name__ == '__main__':
- ipfs_module = IPFSModule()
- from commune.model.transformer.module import TransformerModel
- model = TransformerModel.deploy()
- import sys
- st.write(ipfs_module.save_model('model',model.model))
-
- # # IPFSModule.test()
-
- # # file_meta = module.put_json('hey', {'hey': {}})
- # # st.write(module.cat(file_meta['Hash'], offset=5, length=2))
- # module.test()
- # module.get('QmPgWfmTAH6bo6aJc1JoLuaDLH6A6vCpyVjy57YFK6Fr8m', '/tmp/hey')
diff --git a/commune/modules/client/ipfs/ipfs.yaml b/commune/modules/client/ipfs/ipfs.yaml
deleted file mode 100755
index 968db706f..000000000
--- a/commune/modules/client/ipfs/ipfs.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: IPFSModule
\ No newline at end of file
diff --git a/commune/modules/client/local/__init__.py b/commune/modules/client/local/__init__.py
deleted file mode 100755
index 2d66721ae..000000000
--- a/commune/modules/client/local/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .local import LocalModule
\ No newline at end of file
diff --git a/commune/modules/client/local/local.py b/commune/modules/client/local/local.py
deleted file mode 100755
index 8acb0c9dc..000000000
--- a/commune/modules/client/local/local.py
+++ /dev/null
@@ -1,237 +0,0 @@
-import streamlit as st
-import fsspec
-from fsspec.implementations.local import LocalFileSystem
-from copy import deepcopy
-import json
-import os
-from typing import *
-import pandas as pd
-import pickle
-LocalFileSystem.root_market = '/'
-
-
-
-
-
-class LocalModule(LocalFileSystem):
- default_cfg = {
- }
- def __init__(self, config=None):
- LocalFileSystem.__init__(self)
- self.config= self.resolve_config(config)
- def ensure_path(self, path):
- """
- ensures a dir_path exists, otherwise, it will create it
- """
- file_extension = self.get_file_extension(path)
- if os.path.isfile(path):
- dir_path = os.path.dirname(path)
- elif os.path.isdir(path):
- dir_path = path
- elif len(file_extension)>0:
- dir_path = os.path.dirname(path)
- else:
- dir_path = os.path.dirname(path)
-
- if not os.path.isdir(dir_path):
- os.makedirs(dir_path)
-
- @staticmethod
- def get_file_extension(path):
- return os.path.splitext(path)[1].replace('.', '')
-
- extension2mode = {
- 'pkl':'pickle',
- 'pickle':'pickle',
- 'json': 'json',
- 'csv': 'csv',
- 'yaml': 'yaml',
- 'pth': 'torch.state_dict',
- 'onnx': 'onnx'
- }
-
- supported_modes = ['pickle', 'json']
-
-
- def resolve_mode_from_path(self, path):
- mode = self.extension2mode[self.get_file_extension(path)]
- assert mode in self.supported_modes
- return mode
-
- def put_json(self, path, data):
- # Directly from dictionary
- self.ensure_path(path)
- data_type = type(data)
- if data_type in [dict, list, tuple, set, float, str, int]:
- with open(path, 'w') as outfile:
- json.dump(data, outfile)
- elif data_type in [pd.DataFrame]:
- with open(path, 'w') as outfile:
- data.to_json(outfile)
- else:
- raise NotImplementedError(f"{data_type}, is not supported")
-
-
- def get_json(self, path, handle_error = False, return_type='dict', **kwargs):
- try:
- data = json.loads(self.cat(path))
- except FileNotFoundError as e:
- if handle_error:
- return None
- else:
- raise e
-
- if return_type in ['dict', 'json']:
- data = data
- elif return_type in ['pandas', 'pd']:
- data = pd.DataFrame(data)
- elif return_type in ['torch']:
- torch.tensor
- return data
-
- def put_pickle(self, path:str, data):
- with self.open(path,'wb') as f:
- pickle.dump(data, f, protocol= pickle.HIGHEST_PROTOCOL)
-
- def get_pickle(self, path, handle_error = False):
- try:
- with self.open(path, 'rb') as f:
- return pickle.load(f)
- except FileNotFoundError as e:
- if handle_error:
- return None
- else:
- raise e
-
- def put_object(self, path:str, data:Any, mode:str=None,**kwargs):
- if mode == None:
- mode = self.resolve_mode_from_path(path)
- return getattr(self, f'put_{mode}')(path=path,data=data, **kwargs)
-
- def get_object(self, path:str, mode:str=None, **kwargs):
- if mode == None:
- mode = self.resolve_mode_from_path(path)
- return getattr(self, f'get_{mode}')(path=path, **kwargs)
-
- @staticmethod
- def funcs(module, return_dict=True):
- fn_list = dir(module)
-
- final_fns = []
- if return_dict:
- final_fns = {}
-
- for fn in fn_list:
- if not (fn.startswith('__') and fn.endswith('__')) and not fn.startswith('_'):
-
- fn_object = getattr(module, fn)
- if callable(fn_object):
- if return_dict:
- final_fns[fn] = fn_object
- else:
- final_fns.append(fn)
-
- return final_fns
-
- def resolve_config(self,config):
- if config == None:
- config = self.default_cfg
- else:
- assert isinstance(config, dict)
-
- return config
-
- @classmethod
- def test_json(cls):
- self = cls()
- obj = {'bro': 1}
- dummy_path = '/tmp/commune/bro.json'
- self.put_json(path=dummy_path, data=obj)
- loaded_obj = self.get_json(path=dummy_path)
- assert json.dumps(loaded_obj) == json.dumps(obj)
- return loaded_obj
- @classmethod
- def test_pickle(cls):
- self = cls()
- obj = {'bro': 1}
- dummy_path = '/tmp/commune/bro.json'
- self.put_pickle(path=dummy_path, data=obj)
- loaded_obj = self.get_pickle(path=dummy_path)
- assert json.dumps(loaded_obj) == json.dumps(obj)
- return loaded_obj
-
- @classmethod
- def test(cls):
- import streamlit as st
- for attr in dir(cls):
- if attr[:len('test_')] == 'test_':
- getattr(cls, attr)()
- st.write('PASSED',attr)
-
- def put_json(self, path, data):
- # Directly from dictionary
- self.ensure_path(path)
- data_type = type(data)
- if data_type in [dict, list, tuple, set, float, str, int]:
- with open(path, 'w') as outfile:
- json.dump(data, outfile)
- elif data_type in [pd.DataFrame]:
- with open(path, 'w') as outfile:
- data.to_json(outfile)
- else:
- raise NotImplementedError(f"{data_type}, is not supported")
-
- # async stuff
- async def async_read(path, mode='r'):
- async with aiofiles.open(path, mode=mode) as f:
- data = await f.read()
- return data
- async def async_write(path, data, mode ='w'):
- async with aiofiles.open(path, mode=mode) as f:
- await f.write(data)
-
- async def async_get_json(path, return_type='dict'):
- try:
-
- data = json.loads(await async_read(path))
- except FileNotFoundError as e:
- if handle_error:
- return None
- else:
- raise e
-
- if return_type in ['dict', 'json']:
- data = data
- elif return_type in ['pandas', 'pd']:
- data = pd.DataFrame(data)
- elif return_type in ['torch']:
- torch.tensor
- return data
-
- async def async_put_json( path, data):
- # Directly from dictionary
- data_type = type(data)
- if data_type in [dict, list, tuple, set, float, str, int]:
- json_str = json.dumps(data)
- elif data_type in [pd.DataFrame]:
- json_str = json.dumps(data.to_dict())
- else:
- raise NotImplementedError(f"{data_type}, is not supported")
-
- return await async_write(path, json_str)
-
-
-if __name__ == '__main__':
- import commune
-
- import asyncio
- path = '/tmp/asyncio.txt'
- data = {'bro': [1,2,4,5,5]*100}
- with commune.timer() as t:
- async_put_json(path, data)
- asyncio.run(async_get_json(path))
- st.write(sys.getsizeof(data)/t.seconds)
-
-
- # module = LocalModule()
- # st.write(module.test())
diff --git a/commune/modules/client/pinata/__init__.py b/commune/modules/client/pinata/__init__.py
deleted file mode 100755
index 4e60f2ece..000000000
--- a/commune/modules/client/pinata/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .pinata import PinataModule
\ No newline at end of file
diff --git a/commune/modules/client/pinata/pinata.py b/commune/modules/client/pinata/pinata.py
deleted file mode 100755
index 1f687f082..000000000
--- a/commune/modules/client/pinata/pinata.py
+++ /dev/null
@@ -1,475 +0,0 @@
-import fsspec
-import os
-from fsspec import register_implementation
-import asyncio
-import json
-import pickle
-import io
-from transformers import AutoModel, AutoTokenizer
-from datasets import load_dataset, Dataset
-import os, sys
-import requests
-from commune.client.local import LocalModule
-from commune import Module
-
-import streamlit as st
-
-
-# register_implementation(IPFSFileSystem.protocol, IPFSFileSystem)
-# register_implementation(AsyncIPFSFileSystem.protocol, AsyncIPFSFileSystem)
-
-# with fsspec.open("ipfs://QmZ4tDuvesekSs4qM5ZBKpXiZGun7S2CYtEZRB3DYXkjGx", "r") as f:
-# print(f.read())
-
-
-class PinataModule(Module):
- url = 'https://api.pinata.cloud'
-
- def __init__(self, config=None):
- Module.__init__(self, config=config)
- self.api_key = self.get_api_key(api_key = self.config.get('api_key'))
- self.url = self.config.get('url', f'{self.url}')
- self.local = LocalModule()
-
- def get_api_key(self, api_key=None):
- if api_key == None:
-
- api_key = self.config.get('api_key')
-
- if api_key != None:
- # if the api_key is a env variable
- return api_key
- else:
- # if the api key is just a key itself (raw)
- assert isinstance(api_key, str)
- return api_key
-
- # %% ../nbs/03_pinataapi.ipynb 6
- def generate_apikey(self,
- key_name:str, #Key name
- pinlist:bool=False,#list pins
- userPinnedDataTotal:bool=False, #total data stored
- hashMetadata:bool=True, #metadata
- hashPinPolicy:bool=False, #policy
- pinByHash:bool=True, #pin cid
- pinFileToIPFS:bool=True,#upload file to IPFS
- pinJSONToIPFS:bool=True,#upload json to IPFS
- pinJobs:bool=True,#see pin jobs
- unpin:bool=True,#unpin ipfs cid
- userPinPolicy:bool=True #establish pin policy
-
- ):
-
- url = f"{self.url}/users/generateApiKey"
-
- payload = json.dumps({
- "keyName": key_name,
- "permissions": {
- "endpoints": {
- "data": {
- "pinList": pinlist,
- "userPinnedDataTotal": userPinnedDataTotal
- },
- "pinning": {
- "hashMetadata": hashMetadata,
- "hashPinPolicy": hashPinPolicy,
- "pinByHash": pinByHash,
- "pinFileToIPFS": pinFileToIPFS,
- "pinJSONToIPFS": pinJSONToIPFS,
- "pinJobs": pinJobs,
- "unpin": unpin,
- "userPinPolicy": userPinPolicy
- }
- }
- }
- })
- headers = {
- 'Authorization': f'Bearer {self.api_key}',
- 'Content-Type': 'application/json'
- }
-
- response = requests.post(url, headers=headers, data=payload)
-
- return response
-
-
- # %% ../nbs/03_pinataapi.ipynb 9
- def list_apikeys(self):
-
- url = f"{self.url}/users/apiKeys"
-
- payload={}
- headers = {
- 'Authorization': f'Bearer {self.api_key}'
- }
-
- response = requests.get(url, headers=headers, data=payload)
-
- return response
-
-
- # %% ../nbs/03_pinataapi.ipynb 12
- def revoke_apikey(self,revoke_apikey:str
- ):
- url = f"{self.url}/users/revokeApiKey"
-
- payload = json.dumps({
- "apiKey": revoke_apikey
- })
- headers = {
- 'Authorization': f'Bearer {self.api_key}',
- 'Content-Type': 'application/json'
- }
-
- response = requests.put(url, headers=headers, data=payload)
-
- return response
-
-
- # %% ../nbs/03_pinataapi.ipynb 15
- def upload_file(self,
- name:str, #filename
- fpaths:list, #filepaths
- metadata:dict, #metadata
- cid_version:str="1", #IPFS cid
- directory:bool=False #upload directory
- ):
-
- pinataMetadata = dict({"name":name,"keyvalues":{}})
- pinataMetadata["name"] = name
- pinataMetadata["keyvalues"].update(metadata)
-
- pinataOptions = dict({"cidVersion":cid_version,"directory":directory})
-
-
- url = f"{self.url}/pinning/pinFileToIPFS"
-
- payload={"pinataOptions":json.dumps(pinataOptions),"pinataMetadata":json.dumps(pinataMetadata)}
-
- if directory:
- print("feature is not ready yet")
-
- files=[('file',(name,open(fpaths,'rb'),'application/octet-stream'))]
-
- headers = {
- 'Authorization': f'Bearer {self.api_key}'
- }
-
- response = requests.post(url, headers=headers, data=payload, files=files)
-
- return response
-
- # %% ../nbs/03_pinataapi.ipynb 18
- def upload_jsonfile(self,
- name:str, #filename
- fpaths:list, #filepaths
- metadata:dict, #metadata
- cid_version:str, #IPFS cid
- directory:bool=False #upload directory
- ):
-
- url = f"{self.url}/pinning/pinJSONToIPFS"
-
- payload = json.dumps({
- "pinataOptions": {
- "cidVersion": cid_version
- },
- "pinataMetadata": {
- "name": name,
- "keyvalues": metadata
- },
- "pinataContent": {"file":fpaths}
- })
- headers = {
- 'Authorization': f'Bearer {self.api_key}',
- 'Content-Type': 'application/json'
- }
-
- response = requests.post(url, headers=headers, data=payload)
-
- return response
-
- # %% ../nbs/03_pinataapi.ipynb 21
- def pin(self,
- cid:str, #IPFS cid
- fn=None, #Name of file
- pinataMetadata=None #Add keys and values associated with IPFS CID
- ):
-
- url = f"{self.url}/pinning/pinByHash"
-
- payload = json.dumps({
- "hashToPin": cid,
- "pinataMetadata": {
- "name": fn,
- "keyvalues": pinataMetadata
- }
- })
- headers = {
- 'Authorization': f'Bearer {self.api_key}',
- 'Content-Type': 'application/json'
- }
-
- response = requests.post(url, headers=headers, data=payload)
-
- return response
-
-
- # %% ../nbs/03_pinataapi.ipynb 24
- def unpin(self,
- cid:str #IPFS CID
- ):
-
- url = f"{self.url}/pinning/unpin/{cid}"
-
- payload={}
- headers = {
- 'Authorization': f'Bearer {self.api_key}'
- }
-
- response = requests.delete(url, headers=headers, data=payload)
-
- return response
-
- # %% ../nbs/03_pinataapi.ipynb 29
- def edit_metadata(self,
- cid:str, #IPFS CID
- name:str, #filename
- metadata=None #Add keys and values associated with IPFS CID
- ):
-
- url = f"{self.url}/pinning/hashMetadata"
-
- pinataMetadata = dict({"name":name,"keyvalues":{}})
- pinataMetadata["keyvalues"].update(metadata)
- pinataMetadata["ipfsPinHash"] = cid
-
- payload = json.dumps(pinataMetadata)
- headers = {
- 'Authorization': f'Bearer {self.api_key}',
- 'Content-Type': 'application/json'
- }
-
- response = requests.put(url, headers=headers, data=payload)
-
- return response
-
-
- # %% ../nbs/03_pinataapi.ipynb 34
- def get_pinned_jobs(self,
- params=None # filtering pinned jobs
- ):
-
- '''
- 'sort' - Sort the results by the date added to the pinning queue (see value options below)
- 'ASC' - Sort by ascending dates
- 'DESC' - Sort by descending dates
- 'status' - Filter by the status of the job in the pinning queue (see potential statuses below)
- 'prechecking' - Pinata is running preliminary validations on your pin request.
- 'searching' - Pinata is actively searching for your content on the IPFS network. This may take some time if your content is isolated.
- 'retrieving' - Pinata has located your content and is now in the process of retrieving it.
- 'expired' - Pinata wasn't able to find your content after a day of searching the IPFS network. Please make sure your content is hosted on the IPFS network before trying to pin again.
- 'over_free_limit' - Pinning this object would put you over the free tier limit. Please add a credit card to continue pinning content.
- 'over_max_size' - This object is too large of an item to pin. If you're seeing this, please contact us for a more custom solution.
- 'invalid_object' - The object you're attempting to pin isn't readable by IPFS nodes. Please contact us if you receive this, as we'd like to better understand what you're attempting to pin.
- 'bad_host_node' - You provided a host node that was either invalid or unreachable. Please make sure all provided host nodes are online and reachable.
- 'ipfs_pin_hash' - Retrieve the record for a specific IPFS hash
- 'limit' - Limit the amount of results returned per page of results (default is 5, and max is 1000)
- 'offset' - Provide the record offset for records being returned. This is how you retrieve records on additional pages (default is 0)
- '''
-
- base_url = f'{self.url}/pinning/pinJobs/'
-
- header = {'Authorization': f'Bearer {self.api_key}'}
-
- response = requests.get(base_url, headers=header,params=params)
-
- return response
-
- # %% ../nbs/03_pinataapi.ipynb 37
-
- def get_pinned_files(self,params=None # Filter returned pinned files
- ):
-
- '''
- Query Parameters = params
- hashContains: (string) - Filter on alphanumeric characters inside of pin hashes. Hashes which do not include the characters passed in will not be returned.
- pinStart: (must be in ISO_8601 format) - Exclude pin records that were pinned before the passed in 'pinStart' datetime.
- pinEnd: (must be in ISO_8601 format) - Exclude pin records that were pinned after the passed in 'pinEnd' datetime.
- unpinStart: (must be in ISO_8601 format) - Exclude pin records that were unpinned before the passed in 'unpinStart' datetime.
- unpinEnd: (must be in ISO_8601 format) - Exclude pin records that were unpinned after the passed in 'unpinEnd' datetime.
- pinSizeMin: (integer) - The minimum byte size that pin record you're looking for can have
- pinSizeMax: (integer) - The maximum byte size that pin record you're looking for can have
- status: (string) -
- * Pass in 'all' for both pinned and unpinned records
- * Pass in 'pinned' for just pinned records (hashes that are currently pinned)
- * Pass in 'unpinned' for just unpinned records (previous hashes that are no longer being pinned on pinata)
- pageLimit: (integer) - This sets the amount of records that will be returned per API response. (Max 1000)
- pageOffset: (integer) - This tells the API how far to offset the record responses. For example,
- if there's 30 records that match your query, and you passed in a pageLimit of 10, providing a pageOffset of 10 would return records 11-20.
- '''
-
- base_url = f'{self.url}/data/pinList?'
-
- header = {'Authorization': f'Bearer {self.api_key}'}
-
- response = requests.get(base_url, headers=header,params=params)
-
- return response
-
- ls_pins = get_pinned_files
- ls = get_pinned_files
-
-
- # %% ../nbs/03_pinataapi.ipynb 40
- def get_datausage(self,params=None # Filter returned data usage statistics
- ):
-
- header = {'Authorization': f'Bearer {self.api_key}'}
-
- base_url = f'{self.url}/data/userPinnedDataTotal'
-
- response = requests.get(base_url, headers=header,params=params)
-
- return response
-
- @property
- def tmp_root_path(self):
- return f'/tmp/commune/{self.id}'
-
- def get_temp_path(self, path):
- tmp_path = os.path.join(self.tmp_root_path, path)
- if not os.path.exists(self.tmp_root_path):
- self.local.makedirs(os.path.dirname(path), exist_ok=True)
-
- return tmp_path
-
-
- def save_model(self, model, path:str=None):
-
-
- # self.mkdir(path, create_parents=True)
-
- tmp_path = self.get_temp_path(path=path)
- model.save_pretrained(tmp_path)
- self.mkdirs(path)
-
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path, recursive=True)
-
- return cid
-
- def save_tokenizer(self, tokenizer, path:str=None):
-
-
- # self.mkdir(path, create_parents=True)
-
- tmp_path = self.get_temp_path(path=path)
- tokenizer.save_pretrained(tmp_path)
- self.mkdirs(path)
-
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path, recursive=True)
-
- return cid
-
- def load_tokenizer(self, path:str):
- tmp_path = self.get_temp_path(path=path)
- self.get(lpath=tmp_path, rpath=path )
- model = AutoTokenizer.from_pretrained(tmp_path)
- self.local.rm(tmp_path, recursive=True)
- return model
-
- def load_model(self, path:str):
- tmp_path = self.get_temp_path(path=path)
- self.get(lpath=tmp_path, rpath=path )
- model = AutoModel.from_pretrained(tmp_path)
- # self.fs.local.rm(tmp_path, recursive=True)
- return model
- @st.cache
- def load_dataset(self, path):
- tmp_path = self.get_temp_path(path=path)
- self.get(lpath=tmp_path, rpath=path )
- dataset = Dataset.load_from_disk(tmp_path)
- # self.fs.local.rm(tmp_path, recursive=True)
-
- return dataset
-
- def save_dataset(self, dataset, path:str=None):
- tmp_path = self.get_temp_path(path=path)
- dataset = dataset.save_to_disk(tmp_path)
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- # self.fs.local.rm(tmp_path, recursive=True)
- return cid
-
- def put_json(self, data, path='json_placeholder.pkl'):
- tmp_path = self.get_temp_path(path=path)
- self.local.put_json(path=tmp_path, data=data)
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path)
- return cid
-
- def put_pickle(self, data, path='/pickle_placeholder.pkl'):
- tmp_path = self.get_temp_path(path=path)
- self.local.put_pickle(path=tmp_path, data=data)
- cid = self.force_put(lpath=tmp_path, rpath=path, max_trials=10)
- self.local.rm(tmp_path)
- return cid
- def get_pickle(self, path):
- return pickle.loads(self.cat(path))
-
- def get_json(self, path):
- return json.loads(self.cat(path))
-
- def force_put(self, lpath, rpath, max_trials=10):
- trial_count = 0
- cid = None
- while trial_count Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Forward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List[ bittensor.Endpoint ]` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of inputs. Tensors from x are sent forward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- TODO(const): Allow multiple tensors.
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- modality.
-
- timeout (int):
- Request timeout.
-
- Returns:
- forward_outputs (:obj:`List[ List[ torch.FloatTensor ]]` of shape :obj:`(num_endpoints * (num_synapses * (shape)))`, `required`):
- Output encodings of tensors produced by remote endpoints. Non-responses are zeroes of common shape.
-
- forward_codes (:obj:`List[ List[bittensor.proto.ReturnCodes] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call return ops.
-
- forward_times (:obj:`List[ List [float] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call times
- """
-
- loop = self.get_event_loop()
- return loop.run_until_complete (
- self.async_forward(kwargs=kwargs)
- )
-
-
-
- async def async_forward (
- self,
- fn: None,
- module = None,
- args = None,
- kwargs = None,
- timeout: int = 2,
- min_successes: int = 2,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- # Init clients.
-
-
-
- client = await self.async_get_clients( module )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
- # Make calls.
- running_tasks = []
- for index, (client) in enumerate(clients.items()):
- args, kwargs = self.copy(args), self.copy(kwargs)
- task = asyncio.create_task(
- client.async_forward(*args, **kwargs)
- )
- running_tasks.append(task)
-
-
- outputs = []
-
- while len(running_tasks) > 0:
-
- finished_tasks, running_tasks = await asyncio.wait( running_tasks , return_when=asyncio.FIRST_COMPLETED)
- finished_tasks, running_tasks = list(finished_tasks), list(running_tasks)
-
- responses = await asyncio.gather(*finished_tasks)
-
- for response in responses:
- if min_successes > 0:
- if response[1][0] == 1:
- outputs.append( response )
- if len(outputs) >= min_successes :
- # cancel the rest of the tasks
- [t.cancel() for t in running_tasks]
- running_tasks = [t for t in running_tasks if t.cancelled()]
- assert len(running_tasks) == 0, f'{len(running_tasks)}'
- break
- else:
-
- outputs.append( response)
-
- return outputs
-
-
-
-
- def check_clients( self ):
- r""" Destroys clients based on QPS until there are no more than max_active_clients.
- """
- with self.cull_mutex:
- # ---- Finally: Kill clients over max allowed ----
- if len(self.clients) > self.max_active_clients:
- c = list(self.clients.keys())[0]
- self.clients.pop(c, None)
-
-
-
- async def async_get_client( self,
- module = None,
- timeout=1 ) -> 'commune.Client':
- r""" Finds or creates a client TCP connection associated with the passed Neuron Endpoint
- Returns
- client: (`commune.Client`):
- client with tcp connection endpoint at endpoint.ip:endpoint.port
- """
- # ---- Find the active client for this endpoint ----
-
- modules = self.modules(module)
-
-
- if module == None:
- client = self.choice(self.clients.values())
- if module in self.clients :
- client = self.clients[module]
- else:
- client = await self.async_connect(module, timeout=timeout)
- self.clients[ client.endpoint.hotkey ] = client
-
- return client
-
diff --git a/commune/modules/client/pool/client_pool.yaml b/commune/modules/client/pool/client_pool.yaml
deleted file mode 100644
index a243080ac..000000000
--- a/commune/modules/client/pool/client_pool.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-max_clients: 10
-modules: null
-stats: {}
\ No newline at end of file
diff --git a/commune/modules/client/ray/__init__.py b/commune/modules/client/ray/__init__.py
deleted file mode 100755
index 8bf044da9..000000000
--- a/commune/modules/client/ray/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .ray import RayModule
\ No newline at end of file
diff --git a/commune/modules/client/ray/ray.py b/commune/modules/client/ray/ray.py
deleted file mode 100755
index 0b6e5468c..000000000
--- a/commune/modules/client/ray/ray.py
+++ /dev/null
@@ -1,35 +0,0 @@
-
-import os
-import sys
-import json
-sys.path.append(os.getcwd())
-from commune import Module
-import ray
-import requests
-
-
-class RayModule(Module):
- def __init__(
- self,
- config=None,
- **kwargs
- ):
- Module.__init__(self, config=config, **kwargs)
- self.queue = self.launch(**self.config['servers']['queue'])
- self.object = self.launch(**self.config['servers']['object'])
-
-
-
- # def load_clients(self):
- # # load object server
-
- # self.
-
-if __name__ == '__main__':
- import streamlit as st
- module = RayModule.deploy(actor={'refresh': False, 'wrap': True})
- st.write(module.actor._ray_method_signatures['__init__'][0])
-
-
-
-
diff --git a/commune/modules/client/ray/ray.yaml b/commune/modules/client/ray/ray.yaml
deleted file mode 100755
index 59917ce7f..000000000
--- a/commune/modules/client/ray/ray.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-module: RayModule
-
-client: ['local', 's3']
-
-servers:
- object:
- module: 'ray.server.object'
- queue:
- module: 'ray.server.queue'
-
-ray:
- address: auto
- namespace: default
-
-actor:
- resources:
- 'num_cpus': 0.5
- max_concurrency: 4
- refresh: False
\ No newline at end of file
diff --git a/commune/modules/client/ray/utils.py b/commune/modules/client/ray/utils.py
deleted file mode 100755
index 1aab460fa..000000000
--- a/commune/modules/client/ray/utils.py
+++ /dev/null
@@ -1,17 +0,0 @@
-
-import requests
-
-def graphql_query(query, url):
- # endpoint where you are making the request
- print(url, 'da fuck')
- request = requests.post(url,
- '',
- json={'query': query})
- if request.status_code == 200:
- request_json = request.json()
- if 'data' in request_json:
- return request_json['data']
- else:
- raise Exception('There was an error in the code fam {}', request_json)
- else:
- raise Exception('Query failed. return code is {}. {}'.format(request.status_code, query))
diff --git a/commune/modules/client/rest/__init__.py b/commune/modules/client/rest/__init__.py
deleted file mode 100755
index 0ffa48632..000000000
--- a/commune/modules/client/rest/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .rest import RestModule
\ No newline at end of file
diff --git a/commune/modules/client/rest/rest.py b/commune/modules/client/rest/rest.py
deleted file mode 100755
index 3dc63a6dd..000000000
--- a/commune/modules/client/rest/rest.py
+++ /dev/null
@@ -1,74 +0,0 @@
-
-import os
-import sys
-import json
-sys.path.append(os.getcwd())
-from commune import Module
-import ray
-import requests
-
-class RestModule(Module):
- default_config_path = f"client.rest.module"
- def __init__(
- self,
- config=None
- ):
- Module.__init__(self, config=config)
-
- @property
- def url(self):
- if not hasattr(self,'_url'):
- url = self.config.get('url')
- if not url.startswith('http://'):
- url = 'http://'+url
- if url == None:
- assert 'host' in self.config
- assert 'port' in self.config
- url = f"http://{self.config['host']}:{self.config['port']}"
- self._url = url
-
- return self._url
-
- @url.setter
- def url(self, value:str):
- self._url = value
-
- def resolve_url(self,url ):
- if isinstance(url,str):
- return url
- else:
- assert isinstance(self.url, str)
- return self.url
-
-
- def get(self, url:str=None,endpoint:str=None, params={},**kwargs):
- url = self.resolve_url(url=url)
- if isinstance(endpoint, str):
- url = os.path.join(url, endpoint)
- return requests.get(url=url, params=params, **kwargs).json()
-
- def post(self, url:str=None, endpoint:str=None, **kwargs):
- url = self.resolve_url(url=url)
- if isinstance(endpoint, str):
- url = os.path.join(url, endpoint)
-
- return requests.post(url=url, **kwargs).json()
-
-if __name__ == '__main__':
- import streamlit as st
- rest = RestModule.deploy(actor=False)
- st.write(rest.url)
- # st.write(rest.get(endpoint='module/list'))
- # st.write(rest.get(endpoint='module/start', params={'module': 'gradio.example.module.ExampleModule'}))
- import socket, subprocess
- PORT = 7866
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('', PORT))
- sock.listen(5)
- cli, addr = sock.accept()
- # print(api.get(endpoint='launcher/send',
- # params=dict(module='process.bittensor.module.BitModule', fn='getattr', kwargs='{"key": "n"}')))
-
-
-
-
diff --git a/commune/modules/client/rest/rest.yaml b/commune/modules/client/rest/rest.yaml
deleted file mode 100755
index 5c08c857a..000000000
--- a/commune/modules/client/rest/rest.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-module: RestModule
-url: http://localhost:8000
-
-actor:
- name: rest
- resources:
- 'num_cpus': 0.5
- max_concurrency: 4
- refresh: False
\ No newline at end of file
diff --git a/commune/modules/client/rest/utils.py b/commune/modules/client/rest/utils.py
deleted file mode 100755
index 1aab460fa..000000000
--- a/commune/modules/client/rest/utils.py
+++ /dev/null
@@ -1,17 +0,0 @@
-
-import requests
-
-def graphql_query(query, url):
- # endpoint where you are making the request
- print(url, 'da fuck')
- request = requests.post(url,
- '',
- json={'query': query})
- if request.status_code == 200:
- request_json = request.json()
- if 'data' in request_json:
- return request_json['data']
- else:
- raise Exception('There was an error in the code fam {}', request_json)
- else:
- raise Exception('Query failed. return code is {}. {}'.format(request.status_code, query))
diff --git a/commune/modules/client/s3/__init__.py b/commune/modules/client/s3/__init__.py
deleted file mode 100755
index ea08d9a91..000000000
--- a/commune/modules/client/s3/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .s3 import S3Module
\ No newline at end of file
diff --git a/commune/modules/client/s3/s3.py b/commune/modules/client/s3/s3.py
deleted file mode 100755
index 12f206ae5..000000000
--- a/commune/modules/client/s3/s3.py
+++ /dev/null
@@ -1,4 +0,0 @@
-
-class S3Module:
- def __init__(self, config=None):
- pass
\ No newline at end of file
diff --git a/commune/modules/client/s3/s3.yaml b/commune/modules/client/s3/s3.yaml
deleted file mode 100755
index 01f0044b9..000000000
--- a/commune/modules/client/s3/s3.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: S3Module
\ No newline at end of file
diff --git a/commune/modules/client/virtual.py b/commune/modules/client/virtual.py
deleted file mode 100644
index 2dd6e85bf..000000000
--- a/commune/modules/client/virtual.py
+++ /dev/null
@@ -1,38 +0,0 @@
-
-import commune as c
-from functools import partial
-import asyncio
-
-
-class VirtualClient:
- def __init__(self, module: str ='ReactAgentModule'):
- if isinstance(module, str):
- import commune
- self.module_client = c.connect(module)
- self.loop = self.module_client.loop
- self.success = self.module_client.success
- else:
- self.module_client = module
-
- def remote_call(self, remote_fn: str, *args, return_future= False, timeout:int=10, **kwargs):
- future = asyncio.wait_for(self.module_client.async_forward(fn=remote_fn, args=args, kwargs=kwargs), timeout=timeout)
- loop = asyncio.get_event_loop()
- if return_future:
- return future
- else:
- return loop.run_until_complete(future)
-
- def __str__(self):
- return f''
-
- def __repr__(self):
- return self.__str__()
-
- protected_attributes = [ 'module_client', 'remote_call']
- def __getattr__(self, key):
-
- if key in self.protected_attributes :
- return getattr(self, key)
- else:
- return lambda *args, **kwargs : partial(self.remote_call, (key))( *args, **kwargs)
-
diff --git a/commune/modules/crypto/hash/hash.py b/commune/modules/crypto/hash/hash.py
deleted file mode 100644
index 16c1923ab..000000000
--- a/commune/modules/crypto/hash/hash.py
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-import commune
-
-
-class Hash(commune.Module):
-
- @classmethod
- def hash(cls, x, mode: str='sha256',*args,**kwargs):
- x = cls.python2str(x)
- if mode == 'keccak':
- from web3.main import Web3
- hash_output = Web3.keccak(text=x, *args, **kwargs)
-
- return hash_output.hex()
- elif mode == 'ss58':
- # only works for 32 byte hex strings
- hash_fn = commune.import_object('scalecodec.utils.ss58.ss58_encode')
- # convert to hex
- return hash_fn(x, *args,**kwargs)
- elif mode == 'python':
- return hash(x)
- elif mode == 'md5':
- import hashlib
- return hashlib.md5(x.encode()).hexdigest()
- elif mode == 'sha256':
- import hashlib
- return hashlib.sha256(x.encode()).hexdigest()
- elif mode == 'sha512':
- import hashlib
- return hashlib.sha512(x.encode()).hexdigest()
- elif mode =='sha3_512':
- import hashlib
- return hashlib.sha3_512(x.encode()).hexdigest()
-
- else:
- raise ValueError(f'unknown mode {mode}')
-
- #TODO: add quantum resistant hash functions
-
-
- return hash_output
-
- @classmethod
- def hash_modes(cls):
- return ['keccak', 'ss58', 'python', 'md5', 'sha256', 'sha512', 'sha3_512']
-
- @classmethod
- def test(cls, x='bro'):
- for mode in cls.hash_modes():
- try:
- cls.print(f'SUCCESS {mode}: x -> {cls.hash(x, mode=mode)}', color='green')
- except Exception as e:
- cls.print(f'FAILED {mode}: x -> {e}', color='red')
-
- def __call__(self, *args, **kwargs):
- return self.hash(*args, **kwargs)
-
-if __name__ == "__main__":
- Hash.run()
\ No newline at end of file
diff --git a/commune/modules/crypto/hash/hash.yaml b/commune/modules/crypto/hash/hash.yaml
deleted file mode 100644
index f87c8d159..000000000
--- a/commune/modules/crypto/hash/hash.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: Hash
\ No newline at end of file
diff --git a/commune/modules/crypto/key/aes/aes_key.py b/commune/modules/crypto/key/aes/aes_key.py
deleted file mode 100755
index 9d02396c2..000000000
--- a/commune/modules/crypto/key/aes/aes_key.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import base64
-import hashlib
-from Crypto import Random
-from Crypto.Cipher import AES
-from copy import deepcopy
-import json
-import sys
-import inspect
-import time
-import commune
-class AESKey(commune.Module):
-
- def __init__(self, key:str ):
- self.bs = AES.block_size
- self.key_phrase = hashlib.sha256(key.encode()).digest()
-
- def encrypt(self, data, return_string = True):
- data = self.python2str(data)
- data = self._pad(data)
- iv = Random.new().read(AES.block_size)
- cipher = AES.new(self.key_phrase, AES.MODE_CBC, iv)
-
- encrypted_bytes = base64.b64encode(iv + cipher.encrypt(data.encode()))
- encrypted_data = encrypted_bytes.decode() if return_string else encrypted_bytes
-
- return encrypted_data
-
- def decrypt(self, enc):
- enc = base64.b64decode(enc)
- iv = enc[:AES.block_size]
- cipher = AES.new(self.key_phrase, AES.MODE_CBC, iv)
- try:
- decrypted_data = self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
- except UnicodeDecodeError as e:
- raise Exception('Bro, use another password, this one aint working')
- return self.str2python(decrypted_data)
-
- def _pad(self, s):
- return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
-
- @staticmethod
- def _unpad(s):
- return s[:-ord(s[len(s)-1:])]
-
-
- @classmethod
- def test_encrypt_decrypt(cls, key='dummy'):
- import streamlit as st
- print(inspect.stack()[0][3])
- self = cls(key=key)
- test_objects = [
- [1,2,3,5],
- {'fam': 1, 'bro': 'fam', 'chris': {'sup': [1,'dawg']}},
- 1,
- 'fam',
- ]
- import time
- for test_object in test_objects:
- start_time = time.clock()
- encrypted = self.encrypt(test_object)
- decrypted = self.decrypt(encrypted)
- assert decrypted == test_object, f'FAILED: {test_encrypt_decrypt} {test_object} FAILED'
-
- size_bytes = sys.getsizeof(test_object)
- seconds = time.clock() - start_time
- rate = size_bytes / seconds
-
- print('PASSED test_encrypt_decrypt')
-
- return True
-
-
-
-
-
- @classmethod
- def test_encrypt_decrypt_throughput(cls, key='dummy'):
- import streamlit as st
- self = cls(key=key)
- test_object = [1,2,3,5]*1000000
- start_time = time.clock()
- encrypted = self.encrypt(test_object)
- seconds = time.clock() - start_time
- size_bytes = sys.getsizeof(test_object)
- encrypt_rate = size_bytes / seconds
-
- start_time = time.clock()
- decrypted = self.decrypt(encrypted)
- seconds = time.clock() - start_time
- size_bytes = sys.getsizeof(test_object)
- decrypt_rate = size_bytes / seconds
-
-
- st.write(f'ENCRYPT SPEED (MB per Second): {encrypt_rate//1000}')
- st.write(f'DECRYPT SPEED (MB per Second): {decrypt_rate//1000}')
-
- print('PASSED test_encrypt_decrypt')
-
- return True
-
-
-
-
-
- @classmethod
- def test(cls):
- import streamlit as st
- for attr in dir(cls):
- if attr[:len('test_')] == 'test_':
- getattr(cls, attr)()
- st.write('PASSED',attr)
-
-
- @classmethod
- def streamlit(cls):
- import streamlit as st
- with st.expander('Tests'):
- cls.test()
-
-
-if __name__ =='__main__':
- AESKey.streamlit()
diff --git a/commune/modules/crypto/key/aes/aes_key.yaml b/commune/modules/crypto/key/aes/aes_key.yaml
deleted file mode 100755
index 55d21b436..000000000
--- a/commune/modules/crypto/key/aes/aes_key.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: AESKey
\ No newline at end of file
diff --git a/commune/modules/data/data.py b/commune/modules/data/data.py
deleted file mode 100644
index 54ac695a2..000000000
--- a/commune/modules/data/data.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import commune as c
-import asyncio
-import torch
-class Dataset(c.Module, torch.utils.data.Dataset):
- mode_shortcuts = {
- 'hf': 'text.huggingface',
- 'bt': 'text.bittensor',
- }
- def __init__(self, dataset, config = None, **kwargs):
- config = self.set_config(config, kwargs=)
- self.resolve_config()
- self.logger = logging.getLogger(__name__)
- self.set_dataset(config.)
- self.set_model(config)
- if config.train:
- self.train()
-
-
- @classmethod
- def sample_check(cls, sample):
- return bool(isinstance(sample, dict) and 'input_ids' in sample)
-
- @classmethod
- async def async_sample(cls, dataset = 'dataset.bittensor', max_trials=10, batch_size=1, sequence_length=64, num_batches=10):
- sample = None
- if not hasattr(cls, 'dataset_pool'):
- cls.dataset_pool = c.connect_pool(dataset)
-
- fail_count = 0
-
- while not cls.sample_check(sample) and fail_count < max_trials:
- if len(cls.dataset_pool) == 0:
- cls.dataset_pool = c.connect_pool(dataset)
- try:
- data_idx =cls.choice(list(range(len(cls.dataset_pool))))
- sample = cls.dataset_pool[data_idx].sample(batch_size=batch_size,
- sequence_length=sequence_length)
-
- if not cls.sample_check(sample):
- raise Exception('Sample check failed')
- sample['input_ids'] = sample['input_ids'][:batch_size, -sequence_length:]
-
-
- except Exception as e:
- fail_count += 1
- del cls.dataset_pool[data_idx]
- cls.print(f'ERROR {e} failed to sample, removing dataset {data_idx}, {len(cls.dataset_pool)} remaining', color='red')
- assert cls.sample_check(sample), f'Failed to sample from {dataset} after {max_trials} trials.'
- return sample
-
-
- @classmethod
- def sample(cls, timeout=2, retries = 3, *args, **kwargs):
- try:
- if timeout:
- # Add timeout to the async_get_sample call
- coro = asyncio.wait_for(cls.async_sample(*args, **kwargs), timeout=timeout)
- else:
- coro = cls.async_sample(*args, **kwargs)
-
- return asyncio.run(coro)
- except asyncio.TimeoutError:
- # Handle the timeout error here
- print("Async function call timed out.")
- if retries > 0:
- return cls.sample(timeout=timeout, retries=retries-1, *args, **kwargs)
-
diff --git a/commune/modules/data/hf/data_hf.py b/commune/modules/data/hf/data_hf.py
deleted file mode 100644
index d25b5da56..000000000
--- a/commune/modules/data/hf/data_hf.py
+++ /dev/null
@@ -1,245 +0,0 @@
-import commune as c
-import datasets
-from datasets import load_dataset
-from typing import Dict, List
-
-class DataHF(c.Module):
-
- def __init__(self, config = None, **kwargs):
- config = self.set_config(config, kwargs=kwargs)
- self.set_dataset(path=config.path, name=config.name, split=config.split, streaming=config.streaming)
-
- def __len__(self):
- return len(self.dataset)
-
- @property
- def n(self):
- return len(self)
-
-
- def random_idx(self):
- return c.random_int(len(self))
-
-
- def sample(self, idx:int=None, batch_size:int = 1):
- if batch_size > 1:
- return [self.sample() for i in range(batch_size)]
- idx = self.random_idx() if idx == None else idx
- return self.dataset[idx]
-
-
-
-
- def validate(self, module, num_samples=10):
- for i in range(num_samples):
- idx = self.random_idx()
- sample = self.sample(idx=idx)
- module_sample = module.sample(idx=idx)
- for key in sample.keys():
- if sample[key] != module_sample[key]:
- return 0
- return 1
-
- @classmethod
- def test(cls, *args,**kwargs):
- cls.print('Testing dataset')
- dataset = cls(*args, **kwargs)
- sample = dataset.sample()
- assert isinstance(sample, dict)
- return sample
-
-
- def default_name(self):
- return self.available_names()[0]
-
-
- def set_dataset(self, path:str = None, name:str = None, split:str = None, streaming:bool=None):
-
-
- config = self.config
-
- # resolve path
- path = path if path else config.path
- path = self.config.shortcuts.get(path, path)
- self.dataset_builder = self.get_dataset_builder(path=path)
-
- # resolve name
- name = name if name else config.name
- name = self.default_name() if name == None else name
-
- # raise Exception(f'Loading dataset: {name} from {path}')
-
- # resolve split
- split = split if split else config.split
- streaming = streaming if streaming else config.streaming
- if isinstance(split, str):
- split = [split]
-
- # load dataset
- dataset_map = load_dataset(path=path,
- name=name,
- split=split,
- streaming=streaming)
-
- # set attributes
- self.splits = list(dataset_map.keys())
- self.dataset = list(dataset_map.values())[0]
- self.dataset_map = dataset_map
-
- # update config
- self.config.update({'path': path, 'name': name, 'split': split, 'streaming': streaming, 'splits': self.splits})
-
- return self.dataset
-
- @property
- def data_info(self):
- return self.dataset._info.__dict__
-
- @property
- def features(self):
- return self.dataset._info.__dict__['features']
-
-
- def set_split(self, split):
- self.dataset = self.dataset_map[split]
- return self.dataset
-
- @classmethod
- def list_datasets(cls):
- return cls.getc('datasets')
-
- @classmethod
- def get_dataset_builder( cls, path:str=None, factory_module_path:str=None):
- path = cls.getc('shortcuts').get(path, path)
- if path == None:
- path = cls.getc('path')
- if factory_module_path == None:
-
- assert isinstance(path, str)
- factory_module = datasets.load.dataset_module_factory(path)
- factory_module_path = factory_module.module_path
-
- dataset_builder = datasets.load.import_main_class(factory_module_path)
- return dataset_builder
-
-
-
- def available_names(self):
- return list(self.config_map().keys())
-
- list_names = available_names
-
-
- def configs(self,):
- configs = self.config_map()
- return list(configs.keys())
-
- def config_map(self):
-
- dataset_builder = self.get_dataset_builder(self.config.path)
- configs = [config.__dict__ for config in dataset_builder.BUILDER_CONFIGS]
-
- if len(configs) == 0:
- configs = [dataset_builder._info.__dict__]
- configs[0]['name'] = 'default'
-
- config_map = {config['name']: config for config in configs}
-
- return config_map
-
- @property
- def card(self) -> Dict[str,str]:
- return dict(
- module = self.module_path,
- path = self.path,
- name = self.name,
- split = self.split
- )
-
-
- @classmethod
- def test(cls, *args, **kwargs):
-
- self = cls( *args, **kwargs)
- x = self.sample()
- print(x)
-
-
-
- @classmethod
- def available_datasets(cls, prefix:str='dataset') -> List[str]:
- return [x for x in commune.servers() if x.startswith(prefix)]
-
- @classmethod
- def default_dataset(cls) -> str:
- available_datasets = cls.available_datasets()
- if len(available_datasets) == 0:
- return cls.launch(name='dataset.text.glue', kwargs=dict(path='glue'))
- return commune.connect(dataset_name)
-
-
-
- @classmethod
- def test_multiple(cls):
- for path in cls.list_datasets():
- cls.print(f'TESTING ({cls.module_path()}): {path}', 'yellow')
- self = cls(path=path)
- sample = self.sample(tokenize=False)
- assert 'text' in sample
- sample = self.sample(tokenize=True)
- assert 'input_ids' in sample
- cls.print(f'PASSED ({cls.module_path()}): {path}', 'green')
-
- @classmethod
- def sandbox(cls):
- import streamlit as st
- self = cls()
- for i in range(1000):
- self.sample()
- print(i)
-
- @property
- def name_suffix(self):
- return f'{self.path}'
-
- @classmethod
- def serve(cls, path:str = 'truthqa', tag=None, remote:bool=True, **kwargs):
- server_name = f'data.{path}'
- kwargs = dict(path=path, **kwargs)
- c.print(f'Serving {server_name} with kwargs: {kwargs}')
- name = c.serve(module=cls.module_path(), server_name=server_name, tag=tag, kwargs=kwargs, remote=remote)
- return name
-
-
- @classmethod
- def serve_category(cls, fleet:str = 'qa', remote:bool=True, tag=None, **kwargs):
- fleet = cls.getc(f'fleet.{fleet}')
-
- avoid_ports = []
- for path in fleet:
- port = c.free_port(avoid_ports=avoid_ports)
- cls.serve(path=path, remote=remote, port=port, tag=tag, **kwargs)
- avoid_ports.append(port)
-
- @classmethod
- def fleet(cls, path:str = 'truthful_qa', n:int=5, remote:bool=True, tag=None, **kwargs):
-
- avoid_ports = []
- for i in range(n):
- port = c.free_port(avoid_ports=avoid_ports)
- cls.serve(path=path, remote=remote, port=port, tag=f'{i}' if tag == None else f'{tag}.{i}', **kwargs)
- avoid_ports.append(port)
-
-
- @classmethod
- def validate(cls, module = None, ref_module=None):
- module = c.connect(module)
- ref_module = c.connect(ref_module)
- ref_idx = ref_module.random_idx()
- ref_sample = ref_module.sample(idx=ref_idx)
- reference_sample = module.sample(idx=ref_idx)
-
- module.sample(idx=0)
-
-
-
diff --git a/commune/modules/data/hf/data_hf.yaml b/commune/modules/data/hf/data_hf.yaml
deleted file mode 100644
index aa8ac133a..000000000
--- a/commune/modules/data/hf/data_hf.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-path: super_glue
-name: null
-streaming: False
-split: null
-
-datasets:
- - Hello-SimpleAI/HC3 # human and chatbot responses to a question
- - squad_v2
- - super_glue
- # math
- - camel-ai/math
- # mc
- - truthqa
- - NLPCoreTeam/mmlu_ru
- - math_qa
- - pubmed_qa
- - ai2_arc
-
-
-fleet:
- qa: [truthqa, math_qa, pubmed_qa, ai2_arc]
-
-
-shortcuts:
- pile: EleutherAI/the_pile
- wiki: wikitext
- glue: glue
- camel_math: camel-ai/math
- mmul_ru: NLPCoreTeam/mmlu_ru
- pubmed_qa: pubmed_qa
- truthqa: truthful_qa
\ No newline at end of file
diff --git a/commune/modules/data/text/folder/data_text_folder.yaml b/commune/modules/data/text/folder/data_text_folder.yaml
deleted file mode 100644
index f2a8fffef..000000000
--- a/commune/modules/data/text/folder/data_text_folder.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-folder_path: ./
-suffix: .py
\ No newline at end of file
diff --git a/commune/modules/data/text/realfake/data_text_realfake.yaml b/commune/modules/data/text/realfake/data_text_realfake.yaml
deleted file mode 100644
index 59b3fbcf6..000000000
--- a/commune/modules/data/text/realfake/data_text_realfake.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-folder_path: ./
-suffix: .py
-module_prefix: model
\ No newline at end of file
diff --git a/commune/modules/data/text/truthqa/data_text_truthqa.yaml b/commune/modules/data/text/truthqa/data_text_truthqa.yaml
deleted file mode 100644
index fedcc6a15..000000000
--- a/commune/modules/data/text/truthqa/data_text_truthqa.yaml
+++ /dev/null
@@ -1 +0,0 @@
-path: truthqa
\ No newline at end of file
diff --git a/commune/modules/executor/executor.py b/commune/modules/executor/executor.py
deleted file mode 100644
index 032ec91d5..000000000
--- a/commune/modules/executor/executor.py
+++ /dev/null
@@ -1,217 +0,0 @@
-
-import os
-import sys
-import time
-import queue
-import random
-import weakref
-import itertools
-import threading
-
-from loguru import logger
-from typing import Callable
-import concurrent
-from concurrent.futures._base import Future
-import commune as c
-
-
-# Workers are created as daemon threads. This is done to allow the interpreter
-# to exit when there are still idle threads in a ThreadPoolExecutor's thread
-# pool (i.e. shutdown() was not called). However, allowing workers to die with
-# the interpreter has two undesirable properties:
-# - The workers would still be running during interpreter shutdown,
-# meaning that they would fail in unpredictable ways.
-# - The workers could be killed while evaluating a work item, which could
-# be bad if the callable being evaluated has external side-effects e.g.
-# writing to a file.
-#
-# To work around this problem, an exit handler is installed which tells the
-# workers to exit when their work queues are empty and then waits until the
-# threads finish.
-
-Task = c.module('executor.task')
-NULL_ENTRY = (sys.maxsize, Task(None, (), {}))
-
-class TaskExecutor(c.Module):
- """Base threadpool executor with a priority queue"""
-
- # Used to assign unique thread names when thread_name_prefix is not supplied.
- _counter = itertools.count().__next__
- # submit.__doc__ = _base.Executor.submit.__doc__
- threads_queues = weakref.WeakKeyDictionary()
-
- def __init__(
- self,
- maxsize : int =-1,
- max_workers: int =None,
- thread_name_prefix : str ="",
- ):
- """Initializes a new ThreadPoolExecutor instance.
- Args:
- max_workers: The maximum number of threads that can be used to
- execute the given calls.
- thread_name_prefix: An optional name prefix to give our threads.
- """
-
- max_workers = (os.cpu_count() or 1) * 5 if max_workers is None else max_workers
- if max_workers <= 0:
- raise ValueError("max_workers must be greater than 0")
-
- self.max_workers = max_workers
- self.work_queue = queue.PriorityQueue(maxsize=maxsize)
- self.idle_semaphore = threading.Semaphore(0)
- self.threads = []
- self.broken = False
- self.shutdown = False
- self.shutdown_lock = threading.Lock()
- self.thread_name_prefix = thread_name_prefix or ("ThreadPoolExecutor-%d" % self._counter() )
-
- @property
- def is_empty(self):
- return self.work_queue.empty()
-
-
- def submit(self, fn: Callable, args=None, kwargs=None, timeout=200) -> Future:
- args = args or ()
- kwargs = kwargs or {}
- with self.shutdown_lock:
- if self.broken:
- raise Exception("ThreadPoolExecutor is broken")
-
- if self.shutdown:
- raise RuntimeError("cannot schedule new futures after shutdown")
-
- priority = kwargs.get("priority", 1)
- if "priority" in kwargs:
- del kwargs["priority"]
- task = Task(fn=fn, args=args, kwargs=kwargs, timeout=timeout)
- # add the work item to the queue
- self.work_queue.put((priority, task), block=False)
- # adjust the thread count to match the new task
- self.adjust_thread_count()
-
- # return the future (MAYBE WE CAN RETURN THE TASK ITSELF)
- return task.future
-
-
- def adjust_thread_count(self):
- # if idle threads are available, don't spin new threads
- if self.idle_semaphore.acquire(timeout=0):
- return
-
- # When the executor gets lost, the weakref callback will wake up
- # the worker threads.
- def weakref_cb(_, q=self.work_queue):
- q.put(NULL_ENTRY)
-
- num_threads = len(self.threads)
- if num_threads < self.max_workers:
- thread_name = "%s_%d" % (self.thread_name_prefix or self, num_threads)
- t = threading.Thread(
- name=thread_name,
- target=self.worker,
- args=(
- weakref.ref(self, weakref_cb),
- self.work_queue,
- ),
- )
- t.daemon = True
- t.start()
- self.threads.append(t)
- self.threads_queues[t] = self.work_queue
-
- def shutdown(self, wait=True):
- with self.shutdown_lock:
- self.shutdown = True
- self.work_queue.put(NULL_ENTRY)
- if wait:
- for t in self.threads:
- try:
- t.join(timeout=2)
- except Exception:
- pass
-
- @staticmethod
- def worker(executor_reference, work_queue):
-
- try:
- while True:
- work_item = work_queue.get(block=True)
- priority = work_item[0]
-
- if priority == sys.maxsize:
- # Wake up queue management thread.
- work_queue.put(NULL_ENTRY)
- break
-
- item = work_item[1]
-
- if item is not None:
- item.run()
- # Delete references to object. See issue16284
- del item
- continue
-
- executor = executor_reference()
- # Exit if:
- # - The interpreter is shutting down OR
- # - The executor that owns the worker has been collected OR
- # - The executor that owns the worker has been shutdown.
- if shutdown or executor is None or executor.shutdown:
- # Flag the executor as shutting down as early as possible if it
- # is not gc-ed yet.
- if executor is not None:
- executor.shutdown = True
- # Notice other workers
- work_queue.put(NULL_ENTRY)
- return
- del executor
- except Exception as e:
- c.print(e, color='red')
- c.print("work_item", work_item, color='red')
-
- e = c.detailed_error(e)
- c.print("Exception in worker", e, color='red')
-
- @property
- def num_tasks(self):
- return self.work_queue.qsize()
-
- @classmethod
- def as_completed(futures: list):
- assert isinstance(futures, list), "futures must be a list"
- return [f for f in futures if not f.done()]
-
- @staticmethod
- def wait(futures:list) -> list:
- futures = [futures] if not isinstance(futures, list) else futures
- results = []
- for future in c.as_completed(futures):
- results += [future.result()]
- return results
-
-
- @classmethod
- def test(cls):
- def fn(x):
- result = x*2
- return result
-
- self = cls()
- futures = []
- for i in range(100):
- futures += [self.submit(fn=fn, kwargs=dict(x=i))]
- for future in c.tqdm(futures):
- future.result()
- for i in range(100):
- futures += [self.submit(fn=fn, kwargs=dict(x=i))]
-
- results = c.wait(futures)
-
- while self.num_tasks > 0:
- c.print(self.num_tasks, 'tasks remaining', color='red')
-
-
- return {'success': True, 'msg': 'thread pool test passed'}
-
-
\ No newline at end of file
diff --git a/commune/modules/executor/task.py b/commune/modules/executor/task.py
deleted file mode 100644
index 248b50cfb..000000000
--- a/commune/modules/executor/task.py
+++ /dev/null
@@ -1,111 +0,0 @@
-
-import commune as c
-from concurrent.futures._base import Future
-import time
-import gc
-
-class Task(c.Module):
- def __init__(self, fn:str, args:list, kwargs:dict, timeout:int=10, priority:int=1, path=None, **extra_kwargs):
- self.future = Future()
- self.fn = fn # the function to run
- self.start_time = time.time() # the time the task was created
- self.args = args # the arguments of the task
- self.kwargs = kwargs # the arguments of the task
- self.timeout = timeout # the timeout of the task
- self.priority = priority # the priority of the task
- self.path = path # the path to store the state of the task
- self.status = 'pending' # pending, running, done
- self.data = None # the result of the task
-
- # for the sake of simplicity, we'll just add all the extra kwargs to the task object
- self.extra_kwargs = extra_kwargs
- self.__dict__.update(extra_kwargs)
-
- # store the state of the task if a path is given
- if self.path:
- self.save()
- @property
- def lifetime(self) -> float:
- return time.time() - self.start_time
-
- @property
- def save(self):
- self.put(self.path, self.state)
-
- @property
- def state(self) -> dict:
- return {
- 'fn': self.fn.__name__,
- 'kwargs': self.kwargs,
- 'args': self.args,
- 'timeout': self.timeout,
- 'start_time': self.start_time,
- 'priority': self.lifetime,
- 'status': self.status,
- 'data': self.data,
- **{k: self.__dict__[k] for k,v in self.extra_kwargs.items()}
- }
-
-
-
- def run(self):
- """Run the given work item"""
- # Checks if future is canceled or if work item is stale
- if (not self.future.set_running_or_notify_cancel()) or (
- (time.time() - self.start_time) > self.timeout
- ):
- self.future.set_exception(TimeoutError('Task timed out'))
-
- self.status = 'running'
- try:
- data = self.fn(*self.args, **self.kwargs)
- self.future.set_result(data)
- self.status = 'done'
- except Exception as e:
- # what does this do? A: it sets the exception of the future, and sets the status to failed
- self.future.set_exception(e)
- self.status = 'failed'
- data = c.detailed_error(e)
-
-
- # store the result of the task
- self.data = data
-
- # store the state of the task
- if self.path:
- self.save()
-
- # set the result of the future
-
-
- def result(self) -> object:
- return self.future.result()
-
- @property
- def _condition(self) -> bool:
- return self.future._condition
- @property
- def _state(self, *args, **kwargs) -> bool:
- return self.future._state
-
- @property
- def _waiters(self) -> bool:
- return self.future._waiters
-
- def cancel(self) -> bool:
- self.future.cancel()
-
- def running(self) -> bool:
- return self.future.running()
-
- def done(self) -> bool:
- return self.future.done()
-
- def __lt__(self, other):
- if isinstance(other, Task):
- return self.priority < other.priority
- elif isinstance(other, int):
- return self.priority < other
- else:
- raise TypeError(f"Cannot compare Task with {type(other)}")
-
diff --git a/commune/modules/finetune/LICENSE b/commune/modules/finetune/LICENSE
deleted file mode 100644
index 261eeb9e9..000000000
--- a/commune/modules/finetune/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/commune/modules/finetune/finetune.py b/commune/modules/finetune/finetune.py
deleted file mode 100644
index 63cc618f0..000000000
--- a/commune/modules/finetune/finetune.py
+++ /dev/null
@@ -1,159 +0,0 @@
-import commune as c
-import logging
-
-import torch
-from datasets import load_dataset
-from peft import LoraConfig, get_peft_model, prepare_model_for_int8_training
-from trl import SFTTrainer
-
-from transformers import (
- AutoModelForCausalLM,
- AutoTokenizer,
- BitsAndBytesConfig,
- TrainingArguments,
-)
-
-class FineTuner(c.Module):
-
- quantize_config_map = {'bnb': BitsAndBytesConfig}
-
- def __init__(self, config=None, **kwargs):
- config = self.set_config(config, kwargs=kwargs)
- self.logger = logging.getLogger(__name__)
- self.set_model(config)
- self.train(config)
- def forward(self, prompt_text: str, max_length: int = None):
- max_length = max_length if max_length else self.config.max_length
- try:
- inputs = self.tokenizer.encode(prompt_text, return_tensors="pt").to(self.device)
- with torch.no_grad():
- outputs = self.model.generate(inputs, max_length=max_length, do_sample=True)
- return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
- except Exception as e:
- self.logger.error(f"Failed to generate the text: {e}")
- raise
-
- __call__ = forward
-
- @property
- def checkpoint_path(self) -> str:
- return self.resolve_path( self.config.model + '.' + self.tag)
-
- def load_checkpoint(self):
- if c.exists(self.checkpoint_path):
- self.model.from_pretrained(self.checkpoint_path)
- msg = {'success': True, 'message': 'loaded checkpoint'}
- else:
- msg = {'success': False, 'message': f'No checkpoint found at {self.checkpoint_path}'}
- c.print(msg)
- return msg
-
-
-
- def save_checkpoint(self):
- if not c.exists(self.checkpoint_path):
- c.mkdir(os.path.dirname(self.checkpoint_path))
- self.trainer.model.save_pretrained(self.checkpoint_path)
- msg = {'success': True, 'message': f'saved checkpoint to {self.checkpoint_path}'}
- c.print(msg)
- return msg
-
-
- def train(self, config):
- if config.train == False:
- c.print("Skipping training", color='red')
- self.set_trainer(config)
- for epoch in range(config.trainer.num_epochs):
- c.print(f"Epoch {epoch}")
- self.trainer.train()
- self.save_checkpoint()
-
- def set_trainer(self, config):
- if self.config.trainer.task_type == 'CAUSAL_LM':
- self.peft_config = LoraConfig(**self.config.trainer.lora)
- self.model = prepare_model_for_int8_training(self.model)
- self.model = get_peft_model(self.model, self.peft_config)
- self.trainer = SFTTrainer(
- model=self.model,
- train_dataset=self.dataset,
- peft_config=self.peft_config,
- dataset_text_field=self.config.trainer.dataset_text_field,
- max_seq_length=self.config.trainer.max_seq_length,
- tokenizer=self.tokenizer,
- args=TrainingArguments(**self.config.trainer.args),
- )
- else:
- return NotImplementedError
-
- def generate(self, prompt_text: str, max_length: int = None):
- max_length = max_length if max_length else self.config.max_length
- try:
- inputs = self.tokenizer.encode(prompt_text, return_tensors="pt").to(self.device)
- with torch.no_grad():
- outputs = self.model.generate(inputs, max_length=max_length, do_sample=True)
- return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
- except Exception as e:
- self.logger.error(f"Failed to generate the text: {e}")
- raise
-
- @classmethod
- def ensure_env(cls):
- c.ensure_libs(['transformers', 'datasets', 'trl', 'peft', 'bitsandbytes', 'scipy'])
-
-
-
-
- def set_model(self, config):
- self.tokenizer = AutoTokenizer.from_pretrained(config.model)
-
- '''
- get quantize config
- '''
- if config.quantize.enabled:
- mode = config.quantize.mode
-
- if mode == 'bnb':
- assert config.quantize.config.bnb_4bit_compute_dtype.startswith('torch.')
- config.quantize.config.bnb_4bit_compute_dtype = eval(config.quantize.config.bnb_4bit_compute_dtype)
- quantization_config = self.quantize_config_map[mode](**config.quantize.config)
- else:
- quantization_config = None
-
-
- self.model = AutoModelForCausalLM.from_pretrained(config.model, quantization_config=quantization_config)
- if config.load:
- self.load_checkpoint()
-
- def set_dataset(self, config):
-
- if c.module_exists(config.dataset.get('module', None)):
- self.dataset = c.module(module)(**config.dataset)
- else:
- self.dataset = load_dataset(**config.dataset)
-
- sample = self.dataset[0]
- largest_text_field_chars = 0
- if config.trainer.dataset_text_field is None:
- # FIND THE LARGEST TEXT FIELD IN THE DATASET TO USE AS THE TEXT FIELD
- for k, v in sample.items():
- if isinstance(v, str):
- if len(v) > largest_text_field_chars:
- largest_text_field_chars = len(v)
- config.trainer.dataset_text_field = k
- assert config.trainer.dataset_text_field in sample, f"dataset_text_field {config.trainer.dataset_text_field} not in dataset"
-
- self.config = config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/commune/modules/frontend/frontend.py b/commune/modules/frontend/frontend.py
deleted file mode 100644
index bdca88b7a..000000000
--- a/commune/modules/frontend/frontend.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import commune as c
-
-class Frontend(c.Module):
- def __init__(self, **kwargs):
- config = self.set_config(config=kwargs)
- self.docker = c.module('docker')
- def run(self):
- print('Base run')
-
- frontend_path = c.repo_path + '/frontend'
- compose_path = frontend_path + '/docker-compose.yml'
- def up(self, port=300):
- c.compose(path=self.frontend_path + '/docker-compose.yml')
-
-
- def logs(self):
- c.cmd('docker logs -f frontend.commune.v0')
-
- def docs_path(self):
- return self.frontend_path + '/docs'
-
- def doc_modules_path(self):
- return self.frontend_path + '/docs/modules'
- def docs(self):
- return c.ls(self.docs_path())
-
-
- def copy_docs(self):
- docs_path = self.docs_path()
- module2docpath = c.module2docpath()
-
- for module,module_doc_path in module2docpath.items():
- frontend_module_doc_path = self.doc_modules_path() + '/' + module + '.md'
- c.cp(module_doc_path, frontend_module_doc_path, refresh=True)
- assert c.exists(frontend_module_doc_path)
- c.print('Copied docs for module: ' + module)
-
- return c.ls(docs_path)
-
-
-
-
diff --git a/commune/modules/frontend/frontend.yaml b/commune/modules/frontend/frontend.yaml
deleted file mode 100644
index 7ac5c5e33..000000000
--- a/commune/modules/frontend/frontend.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-return_val: pong
-users:
-- user1
-- user2
-- user3
-- bro
diff --git a/commune/modules/git/git.py b/commune/modules/git/git.py
deleted file mode 100644
index 79f254aae..000000000
--- a/commune/modules/git/git.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import commune as c
-
-
-class Git(c.Module):
-
-
- @staticmethod
- def clone(repo_url:str, target_directory:str = None):
- if target_directory == None:
- target_directory = repo_url.split('/')[-1].split('.')[0]
- else:
- target_directory = c.resolve_path(target_directory)
- import subprocess
-
- # Clone the repository
- subprocess.run(['git', 'clone', repo_url, target_directory])
-
- # Remove the .git directory
- subprocess.run(['rm', '-rf', f'{target_directory}/.git'])
-
-
- @staticmethod
- def content(url='LambdaLabsML/examples/main/stable-diffusion-finetuning/pokemon_finetune.ipynb',
- prefix='https://raw.githubusercontent.com'):
- return c.module('tool.web').rget(url=f'{prefix}/{url}')
-
- submodule_path = c.repo_path + '/repos'
- def add_submodule(self, url, name=None, prefix=submodule_path):
- if name == None:
- name = url.split('/')[-1].split('.')[0].lower()
-
- if prefix != None:
- name = f'{prefix}/{name}'
-
- c.cmd(f'git submodule add {url} {name}')
-
- addsub = add_submodule
-
- @classmethod
- def pull(cls, stash:bool = False, cwd=None):
- if cwd is None:
- cwd = c.libpath
- if stash:
- c.cmd('git stash', cwd=cwd)
- c.cmd('git pull', cwd=cwd)
- return {'success':True, 'message':'pulled'}
-
- @classmethod
- def push(cls, msg:str='update', cwd=None):
- if cwd is None:
- cwd = c.libpath
- c.cmd(f'git add .', cwd=cwd)
- c.cmd(f'git commit -m "{msg}"', bash=True, cwd=cwd)
- c.cmd(f'git push', cwd=cwd)
-
- @classmethod
- def gstat(cls, cwd=None):
- if cwd is None:
- cwd = c.libpath
- return c.cmd(f'git status', cwd=cwd, verbose=False)
-
-
-
-
- @classmethod
- def commit(cls, message='update', push:bool = True):
- c.cmd(f'git commit -m "{message}"')
- if push:
- cls.push()
-
diff --git a/commune/modules/key/dashboard/key_dashboard.py b/commune/modules/key/dashboard/key_dashboard.py
deleted file mode 100644
index 3d01bdf9e..000000000
--- a/commune/modules/key/dashboard/key_dashboard.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import commune as c
-
-class KeyDashboard(c.Module):
- def __init__(self, **kwargs):
- config = self.set_config(kwargs)
-
- def select_key(self,):
- with st.expander('Select Key', expanded=True):
- key = 'module'
- key = st.selectbox('Select Key', self.keys, index=self.key2index[key])
- self.key = c.get_key(key)
- if self.key.path == None:
- self.key.path = key
- self.key_info_dict = self.subspace.key_info(self.key.path, fmt='j')
-
- st.write('Address: ', self.key.ss58_address)
- st.write('Stake', self.key_info_dict.get('stake', 0))
- st.write('Balance', self.key_info_dict.get('balance', 0))
-
- def create_key(self):
- with st.expander('Create Key', expanded=False):
- new_key = st.text_input('Name of Key', '', key='create')
- create_key_button = st.button('Create Key')
- if create_key_button and len(new_key) > 0:
- c.add_key(new_key)
- key = c.get_key(new_key)
-
- def rename_key(self):
- with st.expander('Rename Key', expanded=False):
- old_key = st.selectbox('Select Key', self.keys, index=self.key2index[self.key.path], key='select old rename key')
- new_key = st.text_input('New of Key', '', key='rename')
- rename_key_button = st.button('Rename Key')
- replace_key = st.checkbox('Replace Key')
- if rename_key_button and len(new_key) > 0:
- if c.key_exists(new_key) and not replace_key:
- st.error('Key already exists')
- c.rename_key(old_key,new_key)
- key = c.get_key(new_key)
-
- def remove_key(self):
- with st.form(key='Remove Key'):
- rm_keys = st.multiselect('Select Key(s) to Remove', self.keys, [], key='rm_key')
- rm_key_button = st.form_submit_button('Remove Key')
- if rm_key_button:
- c.rm_keys(rm_keys)
-
- def key_dashboard(self):
- # self.select_key()
- self.create_key()
- self.rename_key()
- self.remove_key()
\ No newline at end of file
diff --git a/commune/modules/key/dashboard/key_dashboard.yaml b/commune/modules/key/dashboard/key_dashboard.yaml
deleted file mode 100644
index 7ac5c5e33..000000000
--- a/commune/modules/key/dashboard/key_dashboard.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-return_val: pong
-users:
-- user1
-- user2
-- user3
-- bro
diff --git a/commune/modules/key/evm/evm_key.py b/commune/modules/key/evm/evm_key.py
deleted file mode 100644
index 50caac9ae..000000000
--- a/commune/modules/key/evm/evm_key.py
+++ /dev/null
@@ -1,315 +0,0 @@
-#
-# Copyright 2022 Ocean Protocol Foundation
-# SPDX-License-Identifier: Apache-2.0
-#
-import logging
-import os
-from typing import Dict, Optional, Union
-import json
-from eth_account.datastructures import SignedMessage
-from eth_account.messages import SignableMessage
-from hexbytes.main import HexBytes
-from web3.main import Web3
-from eth_account.messages import encode_defunct
-from eth_keys import keys
-from copy import deepcopy
-from eth_account import Account
-
-import commune
-from typing import List, Dict, Union, Optional, Any
-
-logger = logging.getLogger(__name__)
-
-
-class EVMAccount(commune.Module, Account):
- _last_tx_count = dict()
- ENV_PRIVATE_KEY = 'PRIVATE_KEY'
- def __init__(
- self,
- *args,
- config = None,
- **kwargs
- ) -> None:
- """Initialises EVMAccount object."""
- # assert private_key, "private_key is required."
- config = self.set_config(config, kwargs=kwargs)
-
- Account.__init__(self, *args, **kwargs)
- self.set_network(config.network)
-
-
- @property
- def private_key(self):
- return self._private_key
-
-
- @property
- def key(self) -> str:
- return self.private_key
-
- @staticmethod
- def reset_tx_count() -> None:
- EVMAccount._last_tx_count = dict()
-
- def get_nonce(self, address: str = None) -> int:
- # We cannot rely on `web3.eth.get_transaction_count` because when sending multiple
- # transactions in a row without wait in between the network may not get the chance to
- # update the transaction count for the self address in time.
- # So we have to manage this internally per self address.
- address = self.resolve_address(address)
- if address not in EVMAccount._last_tx_count:
- EVMAccount._last_tx_count[address] = self.web3.eth.get_transaction_count(address)
- else:
- EVMAccount._last_tx_count[address] += 1
-
- return EVMAccount._last_tx_count[address]
-
-
- def sign_tx(
- self,
- tx: Dict[str, Union[int, str, bytes]],
- ) -> HexBytes:
- if tx.get('nonce') == None:
- tx['nonce'] = self.get_nonce(web3=self.web3, address=self.address)
- if tx.get('gasePrice') == None:
- gas_price = int(self.web3.eth.gas_price * 1.1)
- max_gas_price = os.getenv('ENV_MAX_GAS_PRICE', None)
- if gas_price and max_gas_price:
- gas_price = min(gas_price, max_gas_price)
-
- tx["gasPrice"] = gas_price
-
-
- signed_tx = self.web3.eth.account.sign_transaction(tx, self.private_key)
-
- return signed_tx.rawTransaction
-
- @property
- def nonce(self):
- return self.web3.eth.get_transaction_count(self.address)
-
- @property
- def gas_prices(self):
- return self.web3.eth.generate_gas_price()
-
- @property
- def tx_metadata(self) -> Dict[str, Union[int, str, bytes]]:
- '''
- Default tx metadata
- '''
-
- return {
- 'from': self.address,
- 'nonce': self.nonce,
- 'gasPrice':self.gas_price,
- }
-
- def send_contract_tx(self, fn:str , value=0):
- '''
- send a contract transaction for your python objecs
- '''
- tx_metadata = self.tx_metadata
- tx_metadata['value'] = value
- tx = fn.buildTransaction(tx_metadata)
- tx = self.send_tx(tx)
- return tx
-
- def send_tx(self, tx):
- '''
- Send a transaction
- '''
- rawTransaction = self.sign_tx(tx=tx)
- # 7. Send tx and wait for receipt
- tx_hash = self.web3.eth.send_raw_transaction(rawTransaction)
- tx_receipt = self.web3.eth.wait_for_transaction_receipt(tx_hash)
-
- return tx_receipt.__dict__
-
-
- def resolve_message(self, message) :
- message = self.python2str(message)
- if isinstance(message, str):
- message = encode_defunct(text=message)
- elif isinstance(message, SignableMessage):
- message = message
- else:
- raise NotImplemented
-
- return message
-
-
- def sign(self, message: Union[SignableMessage,str, dict], include_message:bool = True) -> SignedMessage:
- """Sign a transaction.
- Args:
- message: The message to sign.
- signature_only: If True, only the signature is returned.
- """
- signable_message = self.resolve_message(message)
-
- signed_message = self.sign_message(signable_message)
- signed_message_dict = {}
- for k in ['v', 'r', 's', 'signature', 'messageHash']:
- signed_message_dict[k] = getattr(signed_message, k)
- if isinstance(signed_message_dict[k], HexBytes):
- signed_message_dict[k] = signed_message_dict[k].hex()
-
- if include_message:
- signed_message_dict['message'] = message
- signed_message = signed_message_dict
-
-
- return signed_message
-
- @property
- def public_key(self):
- return self.private_key_to_public_key(self.private_key)
-
-
- @staticmethod
- def private_key_to_public_key(private_key: str) -> str:
- '''
- Conert private key to public key
- '''
- private_key_object = keys.PrivateKey(private_key)
- return private_key_object.public_key
-
-
-
- def keys_str(self) -> str:
- s = []
- s += [f"address: {self.address}"]
- if self.private_key is not None:
- s += [f"private key: {self.private_key}"]
- s += [f"public key: {self.public_key}"]
- s += [""]
- return "\n".join(s)
-
- def resolve_web3(self, web3=None):
- if web3 == None:
- web3 == self.web3
- assert web3 != None
- return web3
-
- def resolve_address(self, address=None):
- if address == None:
- address = self.address
- assert address != None
- return address
-
-
- def get_balance(self, token:str=None, address:str=None):
- address = self.resolve_address(address)
-
- if token == None:
- # return native token
- balance = self.web3.eth.get_balance(self.address)
- else:
- raise NotImplemented
-
- return balance
-
- @property
- def accounts(self):
- return self.config.get('accounts', [])
-
-
- @classmethod
- def streamlit(cls):
- import streamlit as st
- st.write(f'### {cls.__name__}')
- self = cls.deploy(actor={'refresh': False, 'wrap': True})
-
-
- def replicate(self, private_key, web3=None):
- return EVMAccount(private_key=private_key, web3=self.web3)
-
-
- def set_network(self, network:str= 'local.main') -> None:
- '''
- Set network
- '''
- if isinstance(network, str):
- network = {
- 'module': 'web3.evm.network',
- 'kwargs': {
- 'network': network
- }
- }
- if network == None:
- network = self.config['network']
-
- # launch network
- self.network = self.launch(**network)
- self.web3 = self.network.web3
-
- @staticmethod
- def hex2str(input:HexBytes) -> str:
- '''
- HexBytes to str
- '''
- return input.hex()
-
- def recover_signer(self, message:Any,
- signature:str,
- vrs:Union[tuple, list]=None):
- '''
- recover
- '''
-
- message = self.resolve_message(message)
- recovered_address = Account.recover_message(message, signature=signature, vrs=vrs)
- return recovered_address
-
- def verify(self, message:Any, signature:str = None, vrs:Union[tuple, list]=None, address:str=None) -> bool:
- '''
- verify message from the signature or vrs based on the address
- '''
- address = self.resolve_address(address)
- recovered_address = self.recover_signer(message, signature=signature, vrs=vrs)
- return bool(recovered_address == address)
-
- @classmethod
- def test_sign(cls):
- self = cls()
- message = {'bro': 'bro'}
- signature = self.sign(message)
- assert self.verify(message, signature=signature['signature'])
-
- @classmethod
- def test_hash(cls):
- self = cls()
- print(self.hash('hello world'))
-
-
- def test(self):
- self.test_sign()
- # self.test_recover_message()
- # self.test_verify_message()
- self.test_hash()
-
-
- @classmethod
- def from_password(cls, password:str, salt:str='commune'):
-
- from web3.auto import w3
- from Crypto.Protocol.KDF import PBKDF2
-
- # Prompt the user for a password and salt
- password = input("Enter password: ")
- # Derive a key using PBKDF2
- key = PBKDF2(password.encode(), salt, dkLen=32, count=100000)
-
- # Create an account using the key
- account = Account.privateKeyToAccount(key)
-
- # Print the account address and private key
- print("Account address:", account.address)
- print("Private key:", account.privateKey.hex())
-
- return account
-
-if __name__ == '__main__':
- EVMAccount.test_hash()
-
-
-
diff --git a/commune/modules/key/evm/evm_key.yaml b/commune/modules/key/evm/evm_key.yaml
deleted file mode 100644
index f6c0f85b3..000000000
--- a/commune/modules/key/evm/evm_key.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-module: EVMAccount
-
-private_key: alice
-
-
-# these are default ganache private keys, do
-accounts:
- alice: '0xbbfbee4961061d506ffbb11dfea64eba16355cbf1d9c29613126ba7fec0aed5d'
- bob: '0x804365e293b9fab9bd11bddd39082396d56d30779efbb3ffb0a6089027902c4a'
- chris: '0x1f52464c2fb44e9b7e0808f2c5fe56d87b73eb3bca0e72c66f9f74d7c6c9a81f'
- dan: '0x905e216d8acdabbd095f11162327c5e6e80cc59a51283732cd4fe1299b33b7a6'
- ellen: '0xe21bbdc4c57125bec3e05467423dfc3da8754d862140550fc7b3d2833ad1bdeb'
- fam: '0xb591fb79dd7065964210e7e527c87f97523da07ef8d16794f09750d5eef959b5'
- greg: '0xfe613f76efbfd03a16624ed8d96777966770f353e83d6f7611c11fdfcdfa48d1'
- helen: '0x52f94fdeaaf7c8551bda5924f2b52ff438125b9b5170c04ea2e268bd945ff155'
\ No newline at end of file
diff --git a/commune/modules/key/key.py b/commune/modules/key/key.py
deleted file mode 100644
index 0d5429d01..000000000
--- a/commune/modules/key/key.py
+++ /dev/null
@@ -1,1254 +0,0 @@
-
-import json
-from scalecodec.utils.ss58 import ss58_encode, ss58_decode, get_ss58_format
-from scalecodec.base import ScaleBytes
-from typing import Union, Optional
-import time
-import binascii
-import re
-import secrets
-from base64 import b64encode
-
-import nacl.bindings
-import nacl.public
-from eth_keys.datatypes import PrivateKey
-
-
-from substrateinterface.constants import DEV_PHRASE
-from substrateinterface.exceptions import ConfigurationError
-from substrateinterface.key import extract_derive_path
-from substrateinterface.utils.ecdsa_helpers import mnemonic_to_ecdsa_private_key, ecdsa_verify, ecdsa_sign
-from substrateinterface.utils.encrypted_json import decode_pair_from_encrypted_json, encode_pair
-
-from bip39 import bip39_to_mini_secret, bip39_generate, bip39_validate
-import sr25519
-import ed25519_zebra
-import commune as c
-
-__all__ = ['Keypair', 'KeypairType', 'MnemonicLanguageCode']
-
-
-class KeypairType:
- """
- Type of cryptography, used in `Keypair` instance to encrypt and sign data
-
- * ED25519 = 0
- * SR25519 = 1
- * ECDSA = 2
-
- """
- ED25519 = 0
- SR25519 = 1
- ECDSA = 2
-
-
-class MnemonicLanguageCode:
- """
- Available language codes to generate mnemonics
-
- * ENGLISH = 'en'
- * CHINESE_SIMPLIFIED = 'zh-hans'
- * CHINESE_TRADITIONAL = 'zh-hant'
- * FRENCH = 'fr'
- * ITALIAN = 'it'
- * JAPANESE = 'ja'
- * KOREAN = 'ko'
- * SPANISH = 'es'
-
- """
- ENGLISH = 'en'
- CHINESE_SIMPLIFIED = 'zh-hans'
- CHINESE_TRADITIONAL = 'zh-hant'
- FRENCH = 'fr'
- ITALIAN = 'it'
- JAPANESE = 'ja'
- KOREAN = 'ko'
- SPANISH = 'es'
-
-
-class Keypair(c.Module):
- keys_path = c.data_path + '/keys.json'
- def __init__(self,
- ss58_address: str = None,
- public_key: Union[bytes, str] = None,
- private_key: Union[bytes, str] = None,
- ss58_format: int = 42,
- seed_hex: Union[str, bytes] = None,
- crypto_type: int = KeypairType.SR25519,
- derive_path: str = None,
- mnemonic: str = None,
- path:str = None,
- ):
- """
- Allows generation of Keypairs from a variety of input combination, such as a public/private key combination,
- mnemonic or URI containing soft and hard derivation paths. With these Keypairs data can be signed and verified
-
- Parameters
- ----------
- ss58_address: Substrate address
- public_key: hex string or bytes of public_key key
- private_key: hex string or bytes of private key
- ss58_format: Substrate address format, default to 42 when omitted
- seed_hex: hex string of seed
- crypto_type: Use KeypairType.SR25519 or KeypairType.ED25519 cryptography for generating the Keypair
- """
-
- # If no arguments are provided, generate a random keypair
- if ss58_address == None and public_key == None and private_key == None and seed_hex == None and mnemonic == None:
- key = self.gen()
- seed_hex = key.__dict__.get('seed_hex', seed_hex)
- private_key = key.__dict__.get('private_key', private_key)
- crypto_type = key.__dict__.get('crypto_type', crypto_type)
- derive_path = key.__dict__.get('derive_path', derive_path)
- ss58_address = key.__dict__.get('ss58_address', ss58_address)
- path = key.__dict__.get('path', path)
- public_key = key.__dict__.get('public_key', public_key)
- ss58_format = key.__dict__.get('ss58_format', ss58_format)
- mnemonic = key.__dict__.get('mnemonic', mnemonic)
-
-
-
- self.crypto_type = crypto_type
- self.seed_hex = seed_hex
- self.derive_path = None
- self.path = path
- self.ss58_format = ss58_format
-
-
- if crypto_type != KeypairType.ECDSA and ss58_address and not public_key:
- public_key = ss58_decode(ss58_address, valid_ss58_format=ss58_format)
-
- if private_key:
- if type(private_key) == str:
- private_key = c.str2bytes(private_key)
-
- if self.crypto_type == KeypairType.SR25519:
- if len(private_key) != 64:
- raise ValueError('Secret key should be 64 bytes long')
- if not public_key:
- public_key = sr25519.public_from_secret_key(private_key)
-
- if self.crypto_type == KeypairType.ECDSA:
- private_key_obj = PrivateKey(private_key)
- public_key = private_key_obj.public_key.to_address()
- ss58_address = private_key_obj.public_key.to_checksum_address()
-
-
-
-
- if not public_key:
- raise ValueError('No SS58 formatted address or public key provided')
-
- if type(public_key) is str:
- public_key = bytes.fromhex(public_key.replace('0x', ''))
-
- if crypto_type == KeypairType.ECDSA:
- if len(public_key) != 20:
- raise ValueError('Public key should be 20 bytes long')
- else:
- if len(public_key) != 32:
- raise ValueError('Public key should be 32 bytes long')
-
- if not ss58_address:
- ss58_address = ss58_encode(public_key, ss58_format=ss58_format)
-
- self.public_key: bytes = public_key
-
- self.ss58_address: str = ss58_address
-
- self.private_key: bytes = private_key
-
- self.mnemonic = mnemonic
-
- @classmethod
- def add_key(cls, path:str, mnemonic:str = None, password:str=None, refresh:bool=False, **kwargs):
-
- if cls.key_exists(path) and not refresh :
- return {'status': 'error', 'message': f'key already exists at {path}'}
- if password != None:
- key_json = cls.encrypt(data=key_json, password=password)
- kwargs['mnemonic'] = mnemonic
- key = cls.gen(**kwargs)
- key.path = path
- key_json = key.to_json()
-
- cls.put(path, key_json)
-
- return json.loads(key_json)
-
- @classmethod
- def rename_key(self, new_path):
- return self.mv_key(self.path, new_path)
-
- @classmethod
- def mv_key(cls, path, new_path):
-
- assert cls.key_exists(path), f'key does not exist at {path}'
- cls.put(new_path, cls.get_key(path).to_json())
- cls.rm_key(path)
- assert cls.key_exists(new_path), f'key does not exist at {new_path}'
- new_key = cls.get_key(new_path)
- return {'success': True, 'message': f'key moved from {path} to {new_path}', 'key': new_key}
-
-
- @classmethod
- def switch_key(cls, path1:str, path2:str):
-
- assert path1 != path2
- assert cls.key_exists(path1), f'key does not exist at {path1}'
- assert cls.key_exists(path2), f'key does not exist at {path2}'
-
-
- before = {
- path1: cls.key2address(path1),
- path2: cls.key2address(path2)
- }
-
-
- key1 = c.get_key(path1)
- key2 = c.get_key(path2)
- cls.put(path1, key2.to_json())
- cls.put(path2, key1.to_json())
-
-
- after = {
- path1 : cls.key2address(path1),
- path2 : cls.key2address(path2)
- }
-
- assert before[path1] == after[path2]
- assert before[path2] == after[path1]
-
- return {'success': True, 'before': before, 'after': after, 'msg': f'switched {path1} and {path2}'}
-
- rename_key = mv_key
-
- @classmethod
- def add_keys(cls, name, n=100, verbose:bool = False, **kwargs):
- response = []
- for i in range(n):
- key_name = f'{name}.{i}'
- if bool == True:
- c.print(f'generating key {key_name}')
- response.append(cls.add_key(key_name, **kwargs))
-
- return response
-
-
- add = add_key
-
- @classmethod
- def key_info(cls, *args, create_if_not_exists=False, **kwargs):
- kwargs['json'] = True
- return cls.get_key(*args, create_if_not_exists=create_if_not_exists, **kwargs)
-
- @classmethod
- def key_info_map(cls, *args, **kwargs):
- return {key: cls.key_info(key) for key in cls.keys(*args, **kwargs)}
-
- @classmethod
- def load_key(cls, path):
- key_info = cls.get(path)
- key_info = c.jload(key_info)
- if key_info['path'] == None:
- key_info['path'] = path.replace('.json', '').split('/')[-1]
-
- cls.add_key(**key_info) /home/endless/commune/data/keys.json
- return {'status': 'success', 'message': f'key loaded from {path}'}
-
-
- @classmethod
- def load_keys(cls, path=keys_path, verbose:bool = False, refresh:bool = False, **kwargs):
- c.print(f'loading keys from {path}', color='green', verbose=verbose)
- key_info_map = c.get_json(path)
- for key_path ,key_info in key_info_map.items():
- cls.add_key( **key_info,refresh=refresh)
- c.print(f'key {key_info["path"]} loaded', color='green', verbose=verbose)
- if key_info['path'] == None:
- key_info['path'] = key_path
- assert cls.get_key(key_info['path']).mnemonic == key_info['mnemonic'], f'mnemonic does not match for key {key_info["path"]}'
- keys = list(key_info_map.keys())
- return {'status': 'success', 'message': f'keys loaded from {path}', 'keys': keys}
-
- @classmethod
- def save_keys(cls, search=None, path=keys_path, verbose:bool = False, **kwargs):
- key_info_map = cls.key_info_map(search)
- cls.put_json(path, key_info_map)
- return {'status': 'success', 'message': f'keys saved to {path}'}
-
-
-
- @classmethod
- def get_key(cls,
- path:str,
- password:str=None,
- json:bool=False,
- create_if_not_exists:bool = True,
- **kwargs):
-
- if cls.key_exists(path) == False:
- if create_if_not_exists == True:
- key = cls.add_key(path, **kwargs)
- c.print(f'key does not exist, generating new key -> {key["ss58_address"]}')
- else:
- raise ValueError(f'key does not exist at --> {path}')
-
- key_json = cls.get(path)
-
- # if key is encrypted, decrypt it
- if c.is_encrypted(key_json):
- key_json = cls.decrypt(data=key_json, password=password)
- if key_json == None:
- c.print({'status': 'error', 'message': f'key is encrypted, please {path} provide password'}, color='red')
- return None
-
-
- if isinstance(key_json, str):
- key_json = c.jload(key_json)
-
-
- if json:
- key_json['path'] = path
- return key_json
- else:
- key = cls.from_json(key_json)
- return key
-
-
-
- @classmethod
- def get_keys(cls, prefix=None):
- keys = {}
- for key in cls.keys():
- if str(key).startswith(str(prefix)) or prefix == None:
- keys[key] = cls.get_key(key)
- if keys[key] == None:
- keys.pop(key)
-
-
-
- return keys
-
-
- @classmethod
- def key2address(cls, prefix=None):
- key2address = { k: v.ss58_address for k,v in cls.get_keys(prefix).items()}
- return key2address
- @classmethod
- def address2key(cls, prefix:Optional[str]=None):
- address2key = { v: k for k,v in cls.key2address().items()}
- if prefix in address2key:
- return address2key[prefix]
- return address2key
-
-
- @classmethod
- def get_address(cls, key):
- return cls.key2address()[key]
- get_addy = get_address
- @classmethod
- def has_address(cls, address):
- return address in cls.address2key()
-
- @classmethod
- def get_key_for_address(cls, address, ):
- return cls.address2key().get(address)
-
- key_storage_path = c.repo_path
-
-
- @classmethod
- def key_paths(cls):
- return cls.ls()
-
-
- @classmethod
- def key2path(cls) -> dict:
-
- key2path = {'.'.join(path.split('/')[-1].split('.')[:-1]):path for path in cls.key_paths()}
- return key2path
-
- @classmethod
- def keys(cls, search : str = None,
- detail:bool=False,
- object:bool=False):
- keys = list(cls.key2path().keys())
- if search != None:
- keys = [key for key in keys if search in key]
-
- # sort keys
- keys = sorted(keys)
-
- assert not (detail and object) , 'detail and object cannot both be true'
- if detail:
- key_names = keys
- keys = {key: cls.get_key(key).to_dict() for key in key_names}
- for key in key_names:
- keys[key].path = key
- if object:
- keys = [cls.get_key(key) for key in keys]
-
-
- return keys
-
- @classmethod
- def key_exists(cls, key):
- key_exists = key in cls.keys()
- if not key_exists:
- addresses = list(cls.key2address().values())
- if key in addresses:
- key_exists = True
- return key_exists
-
-
- @classmethod
- def rm_key(cls, key=None):
-
- key2path = cls.key2path()
- keys = list(key2path.keys())
- if key not in keys:
- raise Exception(f'key {key} not found, available keys: {keys}')
- c.rm(key2path[key])
- assert c.exists(key2path[key]) == False, 'key not deleted'
-
- return {'deleted':[key]}
- @property
- def crypto_type_name(self):
- return self.crypto_type2name(self.crypto_type)
-
-
- @classmethod
- def rm_keys(cls, rm_keys, verbose:bool=False):
-
- if isinstance(rm_keys, str):
- rm_keys = cls.keys(rm_keys)
-
- assert isinstance(rm_keys, list), f'rm_keys must be list, got {type(rm_keys)}'
-
- for rm_key in rm_keys:
- cls.rm_key(rm_key)
-
- return {'removed_keys':rm_keys}
-
- @classmethod
- def rm_all_keys(cls):
- return cls.rm_keys(cls.keys())
- crypto_types = ['ED25519', 'SR25519', 'ECDSA']
-
- @classmethod
- def crypto_type_map(cls):
- crypto_type_map = {k:v for k,v in KeypairType.__dict__.items() if k in cls.crypto_types }
- return crypto_type_map
-
- @classmethod
- def crypto_name2type(cls, name:str):
- crypto_type_map = cls.crypto_type_map()
- name = name.upper()
- for k,v in crypto_type_map.items():
- if k.startswith(name.upper()):
- return v
- return crypto_type_map[name.upper()]
-
- @classmethod
- def crypto_type2name(cls, crypto_type:str):
- crypto_type_map ={v:k for k,v in cls.crypto_type_map().items()}
- return crypto_type_map[crypto_type]
-
-
- @classmethod
- def resolve_crypto_type(cls, crypto_type):
-
- if isinstance(crypto_type, str):
- crypto_type = crypto_type.upper()
- crypto_type = cls.crypto_name2type(crypto_type)
- elif isinstance(crypto_type, int):
- assert crypto_type in list(KeypairType.__dict__.values()), f'crypto_type {crypto_type} not supported'
-
- assert crypto_type in list(KeypairType.__dict__.values()), f'crypto_type {crypto_type} not supported'
- return crypto_type
-
- @classmethod
- def gen_n(cls, n=10, **kwargs):
- keys = []
- for i in range(n):
- keys.append(cls.gen(**kwargs))
-
- return keys
-
-
- @classmethod
- def gen(cls,
- mnemonic:str = None,
- suri:str = None,
- private_key:str = None,
- crypto_type: Union[int,str] = 'sr25519',
- json: bool = False,
- verbose:bool=False,
- **kwargs):
- '''
- yo rody, this is a class method you can gen keys whenever fam
- '''
- mnemonic = kwargs.pop('m', mnemonic)
-
- if mnemonic == None:
- mnemonic = cls.generate_mnemonic()
- if verbose:
- c.print(f'generating {crypto_type} keypair, {suri}', color='green')
-
- crypto_type = cls.resolve_crypto_type(crypto_type)
-
- if suri:
- key = cls.create_from_uri(suri, crypto_type=crypto_type)
- elif mnemonic:
- key = cls.create_from_mnemonic(mnemonic, crypto_type=crypto_type)
- elif private_key:
- key = cls.create_from_private_key(private_key,crypto_type=crypto_type)
- else:
- mnemonic = cls.generate_mnemonic()
- key = cls.create_from_mnemonic(mnemonic, crypto_type=crypto_type)
-
- if json:
- return key.to_json()
-
- return key
-
-
-
- def to_json(self, password: str = None ) -> dict:
- state_dict = self.copy(self.__dict__)
- for k,v in state_dict.items():
- if type(v) in [bytes]:
- state_dict[k] = v.hex()
- if password != None:
- state_dict[k] = self.encrypt(data=state_dict[k], password=password)
-
- state_dict = json.dumps(state_dict)
-
- return state_dict
-
- @classmethod
- def from_json(cls, obj: Union[str, dict], password: str = None) -> dict:
- if type(obj) == str:
- obj = json.loads(obj)
- if obj == None:
- return None
- for k,v in obj.items():
- if c.is_encrypted(obj[k]) and password != None:
- obj[k] = cls.decrypt(data=obj[k], password=password)
-
- return cls(**obj)
-
- @classmethod
- def sand(cls):
-
- for k in cls.gen(suri=2):
-
- password = 'fam'
- enc = cls.encrypt(k, password=password)
- dec = cls.decrypt(enc, password='bro ')
- c.print(k,dec)
-
-
-
-
-
- @classmethod
- def generate_mnemonic(cls, words: int = 12, language_code: str = MnemonicLanguageCode.ENGLISH) -> str:
- """
- Generates a new seed phrase with given amount of words (default 12)
-
- Parameters
- ----------
- words: The amount of words to generate, valid values are 12, 15, 18, 21 and 24
- language_code: The language to use, valid values are: 'en', 'zh-hans', 'zh-hant', 'fr', 'it', 'ja', 'ko', 'es'. Defaults to `MnemonicLanguageCode.ENGLISH`
-
- Returns
- -------
- str: Seed phrase
- """
- return bip39_generate(words, language_code)
-
- @classmethod
- def validate_mnemonic(cls, mnemonic: str, language_code: str = MnemonicLanguageCode.ENGLISH) -> bool:
- """
- Verify if specified mnemonic is valid
-
- Parameters
- ----------
- mnemonic: Seed phrase
- language_code: The language to use, valid values are: 'en', 'zh-hans', 'zh-hant', 'fr', 'it', 'ja', 'ko', 'es'. Defaults to `MnemonicLanguageCode.ENGLISH`
-
- Returns
- -------
- bool
- """
- return bip39_validate(mnemonic, language_code)
-
-
- # def resolve_crypto_type()
- @classmethod
- def create_from_mnemonic(cls, mnemonic: str = None, ss58_format=42, crypto_type=KeypairType.SR25519,
- language_code: str = MnemonicLanguageCode.ENGLISH, return_kwargs:bool = False) -> 'Keypair':
- """
- Create a Keypair for given memonic
-
- Parameters
- ----------
- mnemonic: Seed phrase
- ss58_format: Substrate address format
- crypto_type: Use `KeypairType.SR25519` or `KeypairType.ED25519` cryptography for generating the Keypair
- language_code: The language to use, valid values are: 'en', 'zh-hans', 'zh-hant', 'fr', 'it', 'ja', 'ko', 'es'. Defaults to `MnemonicLanguageCode.ENGLISH`
-
- Returns
- -------
- Keypair
- """
- if not mnemonic:
- mnemonic = cls.generate_mnemonic(language_code=language_code)
-
- if crypto_type == KeypairType.ECDSA:
- if language_code != MnemonicLanguageCode.ENGLISH:
- raise ValueError("ECDSA mnemonic only supports english")
-
- private_key = mnemonic_to_ecdsa_private_key(mnemonic)
- keypair = cls.create_from_private_key(private_key, ss58_format=ss58_format, crypto_type=crypto_type)
-
- else:
- seed_array = bip39_to_mini_secret(mnemonic, "", language_code)
-
- keypair = cls.create_from_seed(
- seed_hex=binascii.hexlify(bytearray(seed_array)).decode("ascii"),
- ss58_format=ss58_format,
- crypto_type=crypto_type,
- return_kwargs=return_kwargs
- )
-
- if return_kwargs:
- kwargs = keypair
- return kwargs
-
-
- keypair.mnemonic = mnemonic
-
-
-
- return keypair
-
- from_mem = create_from_mnemonic
-
- @classmethod
- def create_from_seed(
- cls,
- seed_hex: Union[bytes, str],
- ss58_format: Optional[int] = 42,
- crypto_type=KeypairType.SR25519,
- return_kwargs:bool = False
-
- ) -> 'Keypair':
- """
- Create a Keypair for given seed
-
- Parameters
- ----------
- seed_hex: hex string of seed
- ss58_format: Substrate address format
- crypto_type: Use KeypairType.SR25519 or KeypairType.ED25519 cryptography for generating the Keypair
-
- Returns
- -------
- Keypair
- """
-
- if type(seed_hex) is str:
- seed_hex = bytes.fromhex(seed_hex.replace('0x', ''))
-
- if crypto_type == KeypairType.SR25519:
- public_key, private_key = sr25519.pair_from_seed(seed_hex)
- elif crypto_type == KeypairType.ED25519:
- private_key, public_key = ed25519_zebra.ed_from_seed(seed_hex)
- else:
- raise ValueError('crypto_type "{}" not supported'.format(crypto_type))
-
- ss58_address = ss58_encode(public_key, ss58_format)
-
-
- kwargs = dict(
- ss58_address=ss58_address, public_key=public_key, private_key=private_key,
- ss58_format=ss58_format, crypto_type=crypto_type, seed_hex=seed_hex
- )
-
- if return_kwargs:
- return kwargs
- else:
- return cls(**kwargs)
-
-
- @classmethod
- def create_from_uri(
- cls,
- suri: str,
- ss58_format: Optional[int] = 42,
- crypto_type=KeypairType.SR25519,
- language_code: str = MnemonicLanguageCode.ENGLISH
- ) -> 'Keypair':
- """
- Creates Keypair for specified suri in following format: `[mnemonic]/[soft-path]//[hard-path]`
-
- Parameters
- ----------
- suri:
- ss58_format: Substrate address format
- crypto_type: Use KeypairType.SR25519 or KeypairType.ED25519 cryptography for generating the Keypair
- language_code: The language to use, valid values are: 'en', 'zh-hans', 'zh-hant', 'fr', 'it', 'ja', 'ko', 'es'. Defaults to `MnemonicLanguageCode.ENGLISH`
-
- Returns
- -------
- Keypair
- """
- crypto_type = cls.resolve_crypto_type(crypto_type)
- if not suri.startswith('//'):
- suri = '//' + suri
-
- if suri and suri.startswith('/'):
- suri = DEV_PHRASE + suri
-
- suri_regex = re.match(r'^(?P.[^/]+( .[^/]+)*)(?P(//?[^/]+)*)(///(?P.*))?$', suri)
-
- suri_parts = suri_regex.groupdict()
-
- if crypto_type == KeypairType.ECDSA:
- if language_code != MnemonicLanguageCode.ENGLISH:
- raise ValueError("ECDSA mnemonic only supports english")
-
- private_key = mnemonic_to_ecdsa_private_key(
- mnemonic=suri_parts['phrase'],
- str_derivation_path=suri_parts['path'][1:],
- passphrase=suri_parts['password'] or ''
- )
- derived_keypair = cls.create_from_private_key(private_key, ss58_format=ss58_format, crypto_type=crypto_type)
- else:
-
- if suri_parts['password']:
- raise NotImplementedError(f"Passwords in suri not supported for crypto_type '{crypto_type}'")
-
- derived_keypair = cls.create_from_mnemonic(
- suri_parts['phrase'], ss58_format=ss58_format, crypto_type=crypto_type, language_code=language_code
- )
-
- if suri_parts['path'] != '':
-
- derived_keypair.derive_path = suri_parts['path']
-
- if crypto_type not in [KeypairType.SR25519]:
- raise NotImplementedError('Derivation paths for this crypto type not supported')
-
- derive_junctions = extract_derive_path(suri_parts['path'])
-
- child_pubkey = derived_keypair.public_key
- child_privkey = derived_keypair.private_key
-
- for junction in derive_junctions:
-
- if junction.is_hard:
-
- _, child_pubkey, child_privkey = sr25519.hard_derive_keypair(
- (junction.chain_code, child_pubkey, child_privkey),
- b''
- )
-
- else:
-
- _, child_pubkey, child_privkey = sr25519.derive_keypair(
- (junction.chain_code, child_pubkey, child_privkey),
- b''
- )
-
- derived_keypair = Keypair(public_key=child_pubkey, private_key=child_privkey, ss58_format=ss58_format)
-
- return derived_keypair
-
- @classmethod
- def create_from_private_key(
- cls, private_key: Union[bytes, str], public_key: Union[bytes, str] = None, ss58_address: str = None,
- ss58_format: int = None, crypto_type: int = KeypairType.SR25519
- ) -> 'Keypair':
- """
- Creates Keypair for specified public/private keys
- Parameters
- ----------
- private_key: hex string or bytes of private key
- public_key: hex string or bytes of public key
- ss58_address: Substrate address
- ss58_format: Substrate address format, default = 42
- crypto_type: Use KeypairType.[SR25519|ED25519|ECDSA] cryptography for generating the Keypair
-
- Returns
- -------
- Keypair
- """
-
- return cls(
- ss58_address=ss58_address, public_key=public_key, private_key=private_key,
- ss58_format=ss58_format, crypto_type=crypto_type
- )
-
- @classmethod
- def create_from_encrypted_json(cls, json_data: Union[str, dict], passphrase: str,
- ss58_format: int = None) -> 'Keypair':
- """
- Create a Keypair from a PolkadotJS format encrypted JSON file
-
- Parameters
- ----------
- json_data: Dict or JSON string containing PolkadotJS export format
- passphrase: Used to encrypt the keypair
- ss58_format: Which network ID to use to format the SS58 address (42 for testnet)
-
- Returns
- -------
- Keypair
- """
-
- if type(json_data) is str:
- json_data = json.loads(json_data)
-
- private_key, public_key = decode_pair_from_encrypted_json(json_data, passphrase)
-
- if 'sr25519' in json_data['encoding']['content']:
- crypto_type = KeypairType.SR25519
- elif 'ed25519' in json_data['encoding']['content']:
- crypto_type = KeypairType.ED25519
- # Strip the nonce part of the private key
- private_key = private_key[0:32]
- else:
- raise NotImplementedError("Unknown KeypairType found in JSON")
-
- if ss58_format is None and 'address' in json_data:
- ss58_format = get_ss58_format(json_data['address'])
-
- return cls.create_from_private_key(private_key, public_key, ss58_format=ss58_format, crypto_type=crypto_type)
-
- def export_to_encrypted_json(self, passphrase: str, name: str = None) -> dict:
- """
- Export Keypair to PolkadotJS format encrypted JSON file
-
- Parameters
- ----------
- passphrase: Used to encrypt the keypair
- name: Display name of Keypair used
-
- Returns
- -------
- dict
- """
- if not name:
- name = self.ss58_address
-
- if self.crypto_type != KeypairType.SR25519:
- raise NotImplementedError(f"Cannot create JSON for crypto_type '{self.crypto_type}'")
-
- # Secret key from PolkadotJS is an Ed25519 expanded secret key, so has to be converted
- # https://github.com/polkadot-js/wasm/blob/master/packages/wasm-crypto/src/rs/sr25519.rs#L125
- converted_private_key = sr25519.convert_secret_key_to_ed25519(self.private_key)
-
- encoded = encode_pair(self.public_key, converted_private_key, passphrase)
-
- json_data = {
- "encoded": b64encode(encoded).decode(),
- "encoding": {"content": ["pkcs8", "sr25519"], "type": ["scrypt", "xsalsa20-poly1305"], "version": "3"},
- "address": self.ss58_address,
- "meta": {
- "name": name, "tags": [], "whenCreated": int(time.time())
- }
- }
-
- return json_data
-
- def sign(self, data: Union[ScaleBytes, bytes, str], return_json:bool=False) -> bytes:
- """
- Creates a signature for given data
-
- Parameters
- ----------
- data: data to sign in `Scalebytes`, bytes or hex string format
-
- Returns
- -------
- signature in bytes
-
- """
- if not isinstance(data, str):
- data = c.python2str(data)
- if type(data) is ScaleBytes:
- data = bytes(data.data)
- elif data[0:2] == '0x':
- data = bytes.fromhex(data[2:])
- elif type(data) is str:
- data = data.encode()
-
- if not self.private_key:
- raise ConfigurationError('No private key set to create signatures')
-
- if self.crypto_type == KeypairType.SR25519:
- signature = sr25519.sign((self.public_key, self.private_key), data)
-
- elif self.crypto_type == KeypairType.ED25519:
- signature = ed25519_zebra.ed_sign(self.private_key, data)
-
- elif self.crypto_type == KeypairType.ECDSA:
- signature = ecdsa_sign(self.private_key, data)
-
- else:
- raise ConfigurationError("Crypto type not supported")
-
- if return_json:
- return {
- 'data': data.decode(),
- 'crypto_type': self.crypto_type,
- 'signature': signature.hex(),
- 'address': self.ss58_address,
- }
-
- return signature
-
- def verify(self, data: Union[ScaleBytes, bytes, str, dict], signature: Union[bytes, str] = None, public_key:Optional[str]= None, crypto_type = None) -> bool:
-
- """
- Verifies data with specified signature
-
- Parameters
- ----------
- data: data to be verified in `Scalebytes`, bytes or hex string format
- signature: signature in bytes or hex string format
- public_key: public key in bytes or hex string format
-
- Returns
- -------
- True if data is signed with this Keypair, otherwise False
- """
- data = c.copy(data)
- if isinstance(data, dict):
-
- crypto_type = int(data.pop('crypto_type'))
- signature = data.pop('signature')
- public_key = c.ss58_decode(data.pop('address'))
- if 'data' in data:
- data = data.pop('data')
-
- # if not isinstance(data, str):
- # data = c.python2str(data)
-
-
- if public_key == None:
- public_key = self.public_key
-
- if isinstance(public_key, str):
- public_key = bytes.fromhex(public_key.replace('0x', ''))
-
- if type(data) is ScaleBytes:
- data = bytes(data.data)
- elif data[0:2] == '0x':
- data = bytes.fromhex(data[2:])
- elif type(data) is str:
- data = data.encode()
-
- if type(signature) is str and signature[0:2] == '0x':
- signature = bytes.fromhex(signature[2:])
- elif type(signature) is str:
- signature = bytes.fromhex(signature)
-
- if type(signature) is not bytes:
- raise TypeError("Signature should be of type bytes or a hex-string")
-
- if self.crypto_type == KeypairType.SR25519:
- crypto_verify_fn = sr25519.verify
- elif self.crypto_type == KeypairType.ED25519:
- crypto_verify_fn = ed25519_zebra.ed_verify
- elif self.crypto_type == KeypairType.ECDSA:
- crypto_verify_fn = ecdsa_verify
- else:
- raise ConfigurationError("Crypto type not supported")
-
- verified = crypto_verify_fn(signature, data, public_key)
-
- if not verified:
- # Another attempt with the data wrapped, as discussed in https://github.com/polkadot-js/extension/pull/743
- # Note: As Python apps are trusted sources on its own, no need to wrap data when signing from this lib
- verified = crypto_verify_fn(signature, b'' + data + b'', public_key)
-
- return verified
-
-
-
-
-
-
- @property
- def encryption_key(self):
- password = None
- for k in ['private_key', 'mnemonic', 'sed_hex']:
- if hasattr(self, k):
- v = getattr(self, k)
- if type(v) in [bytes]:
- v = v.hex()
- assert type(v) is str, f"Encryption key should be a string, not {type(v)}"
-
- assert password is not None, "No encryption key found, please make sure you have set either private_key, mnemonic or seed_hex"
-
- return password
-
-
-
- @property
- def aes_key(self):
- if not hasattr(self, '_aes_key'):
- password = self.private_key
- self._aes_key = c.module('key.aes')(c.bytes2str(password))
- return self._aes_key
-
-
-
- def encrypt(self, data: Union[str, bytes], password: str = None, **kwargs) -> bytes:
- return self.aes_key.encrypt(data, **kwargs)
-
- def decrypt(self, data: Union[str, bytes]) -> bytes:
- return self.aes_key.decrypt(data)
-
-
-
- def encrypt_message(
- self, message: Union[bytes, str], recipient_public_key: bytes, nonce: bytes = secrets.token_bytes(24),
- ) -> bytes:
- """
- Encrypts message with for specified recipient
-
- Parameters
- ----------
- message: message to be encrypted, bytes or string
- recipient_public_key: recipient's public key
- nonce: the nonce to use in the encryption
-
- Returns
- -------
- Encrypted message
- """
-
- if not self.private_key:
- raise ConfigurationError('No private key set to encrypt')
- if self.crypto_type != KeypairType.ED25519:
- raise ConfigurationError('Only ed25519 keypair type supported')
-
-
- curve25519_public_key = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(recipient_public_key)
- recipient = nacl.public.PublicKey(curve25519_public_key)
- private_key = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(self.private_key + self.public_key)
- sender = nacl.public.PrivateKey(private_key)
- box = nacl.public.Box(sender, recipient)
- return box.encrypt(message if isinstance(message, bytes) else message.encode("utf-8"), nonce)
-
- def decrypt_message(self, encrypted_message_with_nonce: bytes, sender_public_key: bytes) -> bytes:
- """
- Decrypts message from a specified sender
-
- Parameters
- ----------
- encrypted_message_with_nonce: message to be decrypted
- sender_public_key: sender's public key
-
- Returns
- -------
- Decrypted message
- """
-
- if not self.private_key:
- raise ConfigurationError('No private key set to decrypt')
- if self.crypto_type != KeypairType.ED25519:
- raise ConfigurationError('Only ed25519 keypair type supported')
- private_key = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(self.private_key + self.public_key)
- recipient = nacl.public.PrivateKey(private_key)
- curve25519_public_key = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(sender_public_key)
- sender = nacl.public.PublicKey(curve25519_public_key)
- return nacl.public.Box(recipient, sender).decrypt(encrypted_message_with_nonce)
-
- @classmethod
- def sandbox(cls ):
- key = cls.create_from_uri('//Alice')
- c.print(c.module('bittensor').get_balance(key.ss58_address))
-
- @classmethod
- def test(cls):
- self = cls.create_from_uri('//Alice')
- test_fns = [fn for fn in dir(self) if fn.startswith('test_')]
- num_tests = len(test_fns)
- for i, fn in enumerate(test_fns):
- try:
- getattr(self, fn)()
- except Exception as e:
- e = c.detailed_error(e)
- c.print(f'Failed ({i+1}/{num_tests}) {fn} due to {e}', color='red')
- c.print(f'Passed ({i+1}/{num_tests}) {fn}', color='green')
-
-
- @classmethod
- def is_key(cls, key) -> bool:
- return isinstance(key, Keypair)
-
- def test_signing(self):
- sig = self.sign('test')
- assert self.verify('test',sig, bytes.fromhex(self.public_key.hex()))
- assert self.verify('test',sig, self.public_key)
-
- def test_encryption(self):
- for o in ['test', {'fam': 1}, 1, 1.2, [0,2,4,]]:
- auth = self.encrypt(o)
- c.print(auth)
- assert self.decrypt(auth) == o, f'Encryption failed, {self.decrypt(auth)} != {o}'
- c.print(f'Passed encryption test for {o}', color='green')
-
- def test_key_management(self):
- if self.key_exists('test'):
- self.rm_key('test')
- key1 = self.get_key('test')
- assert self.key_exists('test'), f'Key management failed, key still exists'
- self.mv_key('test', 'test2')
- key2 = self.get_key('test2')
- assert key1.ss58_address == key2.ss58_address, f'Key management failed, {key1.ss58_address} != {key2.ss58_address}'
- assert self.key_exists('test2'), f'Key management failed, key does not exist'
- assert not self.key_exists('test'), f'Key management failed, key still exists'
- self.mv_key('test2', 'test')
- assert self.key_exists('test'), f'Key management failed, key does not exist'
- assert not self.key_exists('test2'), f'Key management failed, key still exists'
- self.rm_key('test')
- assert not self.key_exists('test'), f'Key management failed, key still exists'
-
- @classmethod
- def getmem(cls, key):
- return cls.get_key(key).mnemonic
- mem = getmem
- def __str__(self):
- return f''
-
- mems_path = c.repo_path + '/data/keymems.json'
-
- @classmethod
- def savemems(cls, path=mems_path):
- c.print(f'saving mems to {path}')
- mems = cls.mems()
- c.put_json(path, mems)
- return {'saved_mems':list(mems.keys()), 'path':path}
-
- @classmethod
- def loadmems(cls, path=mems_path, **kwargs):
- mems = c.load_json(path)
- for k,mem in mems.items():
- cls.add_key(k, mem, **kwargs)
- return {'loaded_mems':list(mems.keys()), 'path':path}
-
- @classmethod
- def mems(cls, search=None):
- mems = {}
- for key in cls.keys():
- mems[key] = cls.getmem(key)
-
- if search:
- mems = {k:v for k,v in mems.items() if search in k or search in v}
- return mems
-
- def __repr__(self):
- return self.__str__()
-
- def state_dict(self):
- return self.__dict__
-
- to_dict = state_dict
- @classmethod
- def dashboard(cls):
- import streamlit as st
- self = cls.gen()
-
-
- keys = self.keys()
-
- selected_keys = st.multiselect('Keys', keys)
- buttons = {}
- for key_name in selected_keys:
- key = cls.get_key(key_name)
- with st.expander('Key Info'):
- st.write(key.to_dict())
-
-
- buttons[key_name] = {}
- buttons[key_name]['sign'] = st.button('Sign', key_name)
-
- st.write(self.keys())
-
- @classmethod
- def key2type(cls):
- keys = cls.keys(object=True)
- return {k.path: k.crypto_type_name for k in keys}
- @classmethod
- def key2mem(cls, search=None):
- keys = cls.keys(search, object=True)
- key2mem = {k.path: k.mnemonic for k in keys}
- return key2mem
-
- @classmethod
- def type2keys(cls):
- type2keys = {}
- key2type = cls.key2type()
- for k,t in key2type.items():
- type2keys[t] = type2keys.get(t, []) + [k]
- return type2keys
-
- @classmethod
- def pubkey2multihash(cls, pk:bytes) -> str:
- import multihash
- hashed_public_key = multihash.encode(pk, code=multihash.SHA2_256)
- return hashed_public_key.hex()
-
-
-
- @classmethod
- def duplicate_keys(cls) -> dict:
-
- key2address = cls.key2address()
- duplicate_keys = {}
-
- for k,a in key2address.items():
- if a not in duplicate_keys:
- duplicate_keys[a] = []
-
- duplicate_keys[a] += [k]
-
- return {k:v for k,v in duplicate_keys.items() if len(v) > 1}
-
- @classmethod
- def clean(cls):
- key2adress = c.key2address()
- for k,a in key2adress.items():
- if c.key_exists(a):
- c.print(f'removing {a}', color='red')
- c.rm_key(a)
- c.print('cleaning', k, a, c.key_exists(a))
-
-
- @staticmethod
- def is_valid_ss58_address( address: str, valid_ss58_format:int=42 ) -> bool:
- """
- Checks if the given address is a valid ss58 address.
-
- Args:
- address(str): The address to check.
-
- Returns:
- True if the address is a valid ss58 address for Bittensor, False otherwise.
- """
- from substrateinterface.utils import ss58
- try:
- return ss58.is_valid_ss58_address( address, valid_ss58_format=valid_ss58_format ) # Default substrate ss58 format (legacy)
- except Exception as e:
- return False
-
- @classmethod
- def from_private_key(cls, private_key:str):
- return cls(private_key=private_key)
\ No newline at end of file
diff --git a/commune/modules/key/key_docs.md b/commune/modules/key/key_docs.md
deleted file mode 100644
index 44a2c6659..000000000
--- a/commune/modules/key/key_docs.md
+++ /dev/null
@@ -1,97 +0,0 @@
-```markdown
-# Key Management
-
-In this tutorial, we'll explore the usage of the `commune` Python package for managing keys, balances, stakes, and key statistics.
-
-## Getting Started
-
-First, you need to import the `commune` module:
-
-```python
-import commune as c
-```
-
-## Listing Keys
-
-To start, let's list all the available keys using the `keys()` function:
-
-```python
-c.keys()
-```
-
-## Adding and Removing Keys
-
-You can add and remove keys with the following steps:
-
-### Adding a New Key
-
-To add a new key, use the `add_key()` function:
-
-```python
-c.add_key('fam')
-```
-
-### Removing a Key
-
-To remove a key, use the `rm_key()` function:
-
-```python
-c.rm_key('demo') # Replace 'demo' with the key you want to remove
-```
-
-## Saving and Loading Keys
-
-You can save and load keys for future use:
-
-### Saving Keys
-
-To save the keys, use the `save_keys()` function:
-
-```python
-c.save_keys()
-```
-
-### Loading Keys
-
-To load the saved keys, use the `load_keys()` function:
-
-```python
-c.load_keys()
-```
-
-## Retrieving Balances and Stakes
-
-You can retrieve balance and stake information for a specific key:
-
-### Balance
-
-To get the balance for a key, use the `get_balance()` function:
-
-```python
-c.get_balance('fam') # Replace 'fam' with the key name
-```
-
-### Stake
-
-To get the stake for a key, use the `get_stake()` function:
-
-```python
-c.get_stake('fam') # Replace 'fam' with the key name
-```
-
-## Retrieving Key Statistics
-
-You can also retrieve key statistics for each subnet associated with a key:
-
-```python
-c.key_stats('fam') # Replace 'fam' with the key name
-```
-
-## Conclusion
-
-In this tutorial, you learned how to use the `commune` Python package to manage keys, balances, stakes, and key statistics. Feel free to explore further and adapt these concepts to your specific use cases.
-
-Remember to refer to the official documentation of the `commune` package for more detailed information and additional features.
-```
-
-Feel free to adjust the formatting or wording to better match your preferred style or context!
\ No newline at end of file
diff --git a/commune/modules/model/bitapai/bitapai.md b/commune/modules/model/bitapai/bitapai.md
deleted file mode 100644
index cf01b8bff..000000000
--- a/commune/modules/model/bitapai/bitapai.md
+++ /dev/null
@@ -1,55 +0,0 @@
-
-# **BITAPAI**
-
-## Setting a Bitapai Key
-
-To set a Bitapai key, use the following command:
-
-```bash
-c model.bitapai add_api_key YOUR_API_KEY
-```
-
-Once this is done, you won't need to specify the key every time you start your module. The key will be saved in the module's folder at `.commune/model.bitapai/api_keys.json`.
-
-To remove an API key, use:
-
-```bash
-c model.bitapai rm_api_key YOUR_API_KEY
-```
-
-To list all API keys:
-
-```bash
-c model.bitapai api_keys
-```
-
-## Serving the Model
-
-To serve the model with a specific tag and API key, use the following command:
-
-```bash
-c model.bitapai serve tag=10 api_key=....
-```
-
-## Registering the Model
-
-To register the model with a specific tag and name, use:
-
-```bash
-c model.bitapai register api_key=.... tag=10
-```
-
-This will set the name to `model.bitapai::10`.
-
-## Testing the Model
-
-To test the model, use:
-
-```bash
-c model.bitapai forward "whatup"
-```
-
-**Response:**
-```
-Hello! How can I assist you today? Is there anything in particular that you would like me to know about yourself or the task at hand? Let me help make your day more productive and stress-free. Just tell me what it is you need!
-```
diff --git a/commune/modules/model/bitapai/bitapai.py b/commune/modules/model/bitapai/bitapai.py
deleted file mode 100644
index 68552e8c5..000000000
--- a/commune/modules/model/bitapai/bitapai.py
+++ /dev/null
@@ -1,135 +0,0 @@
-import http.client
-import json
-import commune as c
-
-
-
-
-class BitAPAI(c.Module):
-
- whitelist = ['forward', 'chat', 'ask', 'generate']
-
- def __init__(self, config=None, **kwargs):
- config = self.set_config(config=config, kwargs=kwargs)
- self.conn = http.client.HTTPSConnection(self.config.host)
- self.set_api_key(api_key=config.api_key, cache=config.cache_key)
-
- def set_api_key(self, api_key:str, cache:bool = True):
- if api_key == None:
- api_key = self.get_api_key()
-
-
- self.api_key = api_key
- if cache:
- self.add_api_key(api_key)
-
- assert isinstance(api_key, str)
-
-
-
- def forward( self,
- text:str ,
- # api default is 20, I would not go less than 10 with current network conditions
- # larger number = higher query spread across top miners but slightly longer query time
- count:int = 300,
- # changed to False, I assume you only want a single repsonse so it will return a single random from the pool of valid responses
- return_all:bool = False,
- # added exclude_unavailable to ensure no empty responses are returned
- exclude_unavailable:bool = True,
- uids: list = None,
- api_key:str = None,
- history:list=None) -> str:
- api_key = api_key if api_key != None else self.api_key
- # build payload
-
-
- payload = {
- 'messages':
- [
- {
- "role": "system",
- "content": "You are an AI assistant"
- },
- {
- "role": "user",
- "content": text
- }
- ],
- "count": count,
- "return_all": return_all,
- # added return all here
- "exclude_unavailable": exclude_unavailable
-
- }
- if uids is not None:
- payload['uids'] = uids
-
- if history is not None:
- assert isinstance(history, list)
- assert len(history) > 0
- assert all([isinstance(i, dict) for i in history])
- payload = payload[:1] + history + payload[1:]
-
-
- payload = json.dumps(payload)
- headers = {
- 'Content-Type': 'application/json',
- 'X-API-KEY': api_key
- }
-
-
- self.conn.request("POST", "/text", payload, headers)
-
-
- res = self.conn.getresponse()
- data = res.read().decode("utf-8")
- data = json.loads(data)
- c.print(len(data['choices']))
-
- return data['choices'][0]['message']['content']
-
-
- talk = generate = forward
-
- def test(self):
- return self.forward("hello")
-
-
- ## API MANAGEMENT ##
-
- @classmethod
- def add_api_key(cls, api_key:str):
- assert isinstance(api_key, str)
- api_keys = cls.get('api_keys', [])
- api_keys.append(api_key)
- api_keys = list(set(api_keys))
- cls.put('api_keys', api_keys)
- return {'api_keys': api_keys}
-
-
- @classmethod
- def rm_api_key(cls, api_key:str):
- assert isinstance(api_key, str)
- api_keys = cls.get('api_keys', [])
- for i in range(len(api_keys)):
- if api_key == api_keys[i]:
- api_keys.pop(i)
- break
-
- cls.put('api_keys', api_keys)
- return {'api_keys': api_keys}
-
-
- @classmethod
- def get_api_key(cls):
- api_keys = cls.get('api_keys', [])
- if len(api_keys) == 0:
- return None
- else:
- return c.choice(api_keys)
-
- @classmethod
- def api_keys(cls):
- return cls.get('api_keys', [])
-
-
\ No newline at end of file
diff --git a/commune/modules/model/bt/dendrite/dendrite_model.yaml b/commune/modules/model/bt/dendrite/dendrite_model.yaml
deleted file mode 100644
index 96d64fd52..000000000
--- a/commune/modules/model/bt/dendrite/dendrite_model.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: DendriteModel
\ No newline at end of file
diff --git a/commune/modules/model/chat/anthropic.py b/commune/modules/model/chat/anthropic.py
deleted file mode 100644
index f51d26290..000000000
--- a/commune/modules/model/chat/anthropic.py
+++ /dev/null
@@ -1,197 +0,0 @@
-from typing import Any, AsyncIterator, Dict, Iterator, List, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.llms.anthropic import _AnthropicCommon
-from langchain.schema import (
- ChatGeneration,
- ChatResult,
-)
-from langchain.schema.messages import (
- AIMessage,
- AIMessageChunk,
- BaseMessage,
- ChatMessage,
- HumanMessage,
- SystemMessage,
-)
-from langchain.schema.output import ChatGenerationChunk
-
-import commune as c
-class ChatAnthropic(c.Module, BaseChatModel, _AnthropicCommon):
- """`Anthropic` chat large language models.
-
- To use, you should have the ``anthropic`` python package installed, and the
- environment variable ``ANTHROPIC_API_KEY`` set with your API key, or pass
- it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- import anthropic
- from langchain.chat_models import ChatAnthropic
- model = ChatAnthropic(model="", anthropic_api_key="my-api-key")
- """
-
- class Config:
- """Configuration for this pydantic object."""
-
- allow_population_by_field_name = True
- arbitrary_types_allowed = True
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"anthropic_api_key": "ANTHROPIC_API_KEY"}
-
- @property
- def _llm_type(self) -> str:
- """Return type of chat model."""
- return "anthropic-chat"
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- def _convert_one_message_to_text(self, message: BaseMessage) -> str:
- if isinstance(message, ChatMessage):
- message_text = f"\n\n{message.role.capitalize()}: {message.content}"
- elif isinstance(message, HumanMessage):
- message_text = f"{self.HUMAN_PROMPT} {message.content}"
- elif isinstance(message, AIMessage):
- message_text = f"{self.AI_PROMPT} {message.content}"
- elif isinstance(message, SystemMessage):
- message_text = f"{self.HUMAN_PROMPT} {message.content}"
- else:
- raise ValueError(f"Got unknown type {message}")
- return message_text
-
- def _convert_messages_to_text(self, messages: List[BaseMessage]) -> str:
- """Format a list of strings into a single string with necessary newlines.
-
- Args:
- messages (List[BaseMessage]): List of BaseMessage to combine.
-
- Returns:
- str: Combined string with necessary newlines.
- """
- return "".join(
- self._convert_one_message_to_text(message) for message in messages
- )
-
- def _convert_messages_to_prompt(self, messages: List[BaseMessage]) -> str:
- """Format a list of messages into a full prompt for the Anthropic model
-
- Args:
- messages (List[BaseMessage]): List of BaseMessage to combine.
-
- Returns:
- str: Combined string with necessary HUMAN_PROMPT and AI_PROMPT tags.
- """
- messages = messages.copy() # don't mutate the original list
-
- if not self.AI_PROMPT:
- raise NameError("Please ensure the anthropic package is loaded")
-
- if not isinstance(messages[-1], AIMessage):
- messages.append(AIMessage(content=""))
- text = self._convert_messages_to_text(messages)
- return (
- text.rstrip()
- ) # trim off the trailing ' ' that might come from the "Assistant: "
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- prompt = self._convert_messages_to_prompt(messages)
- params: Dict[str, Any] = {"prompt": prompt, **self._default_params, **kwargs}
- if stop:
- params["stop_sequences"] = stop
-
- stream_resp = self.client.completions.create(**params, stream=True)
- for data in stream_resp:
- delta = data.completion
- yield ChatGenerationChunk(message=AIMessageChunk(content=delta))
- if run_manager:
- run_manager.on_llm_new_token(delta)
-
- async def _astream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- prompt = self._convert_messages_to_prompt(messages)
- params: Dict[str, Any] = {"prompt": prompt, **self._default_params, **kwargs}
- if stop:
- params["stop_sequences"] = stop
-
- stream_resp = await self.async_client.completions.create(**params, stream=True)
- async for data in stream_resp:
- delta = data.completion
- yield ChatGenerationChunk(message=AIMessageChunk(content=delta))
- if run_manager:
- await run_manager.on_llm_new_token(delta)
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if self.streaming:
- completion = ""
- for chunk in self._stream(messages, stop, run_manager, **kwargs):
- completion += chunk.text
- else:
- prompt = self._convert_messages_to_prompt(messages)
- params: Dict[str, Any] = {
- "prompt": prompt,
- **self._default_params,
- **kwargs,
- }
- if stop:
- params["stop_sequences"] = stop
- response = self.client.completions.create(**params)
- completion = response.completion
- message = AIMessage(content=completion)
- return ChatResult(generations=[ChatGeneration(message=message)])
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if self.streaming:
- completion = ""
- async for chunk in self._astream(messages, stop, run_manager, **kwargs):
- completion += chunk.text
- else:
- prompt = self._convert_messages_to_prompt(messages)
- params: Dict[str, Any] = {
- "prompt": prompt,
- **self._default_params,
- **kwargs,
- }
- if stop:
- params["stop_sequences"] = stop
- response = await self.async_client.completions.create(**params)
- completion = response.completion
- message = AIMessage(content=completion)
- return ChatResult(generations=[ChatGeneration(message=message)])
-
- def get_num_tokens(self, text: str) -> int:
- """Calculate number of tokens."""
- if not self.count_tokens:
- raise NameError("Please ensure the anthropic package is loaded")
- return self.count_tokens(text)
diff --git a/commune/modules/model/chat_models/__init__.py b/commune/modules/model/chat_models/__init__.py
deleted file mode 100644
index ee21a2377..000000000
--- a/commune/modules/model/chat_models/__init__.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""**Chat Models** are a variation on language models.
-
-While Chat Models use language models under the hood, the interface they expose
-is a bit different. Rather than expose a "text in, text out" API, they expose
-an interface where "chat messages" are the inputs and outputs.
-
-**Class hierarchy:**
-
-.. code-block::
-
- BaseLanguageModel --> BaseChatModel --> # Examples: ChatOpenAI, ChatGooglePalm
-
-**Main helpers:**
-
-.. code-block::
-
- AIMessage, BaseMessage, HumanMessage
-""" # noqa: E501
-
-from langchain.chat_models.anthropic import ChatAnthropic
-from langchain.chat_models.anyscale import ChatAnyscale
-from langchain.chat_models.azure_openai import AzureChatOpenAI
-from langchain.chat_models.ernie import ErnieBotChat
-from langchain.chat_models.fake import FakeListChatModel
-from langchain.chat_models.google_palm import ChatGooglePalm
-from langchain.chat_models.human import HumanInputChatModel
-from langchain.chat_models.jinachat import JinaChat
-from langchain.chat_models.litellm import ChatLiteLLM
-from langchain.chat_models.mlflow_ai_gateway import ChatMLflowAIGateway
-from langchain.chat_models.ollama import ChatOllama
-from langchain.chat_models.openai import ChatOpenAI
-from langchain.chat_models.promptlayer_openai import PromptLayerChatOpenAI
-from langchain.chat_models.vertexai import ChatVertexAI
-
-__all__ = [
- "ChatOpenAI",
- "AzureChatOpenAI",
- "FakeListChatModel",
- "PromptLayerChatOpenAI",
- "ChatAnthropic",
- "ChatGooglePalm",
- "ChatMLflowAIGateway",
- "ChatOllama",
- "ChatVertexAI",
- "JinaChat",
- "HumanInputChatModel",
- "ChatAnyscale",
- "ChatLiteLLM",
- "ErnieBotChat",
-]
diff --git a/commune/modules/model/chat_models/anyscale.py b/commune/modules/model/chat_models/anyscale.py
deleted file mode 100644
index 2ccae7ca7..000000000
--- a/commune/modules/model/chat_models/anyscale.py
+++ /dev/null
@@ -1,192 +0,0 @@
-"""Anyscale Endpoints chat wrapper. Relies heavily on ChatOpenAI."""
-from __future__ import annotations
-
-import logging
-import os
-import sys
-from typing import TYPE_CHECKING, Optional, Set
-
-import requests
-
-from langchain.adapters.openai import convert_message_to_dict
-from langchain.chat_models.openai import (
- ChatOpenAI,
- _import_tiktoken,
-)
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema.messages import BaseMessage
-from langchain.utils import get_from_dict_or_env
-
-if TYPE_CHECKING:
- import tiktoken
-
-logger = logging.getLogger(__name__)
-
-
-DEFAULT_API_BASE = "https://api.endpoints.anyscale.com/v1"
-DEFAULT_MODEL = "meta-llama/Llama-2-7b-chat-hf"
-
-
-class ChatAnyscale(ChatOpenAI):
- """`Anyscale` Chat large language models.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``ANYSCALE_API_KEY`` set with your API key.
- Alternatively, you can use the anyscale_api_key keyword argument.
-
- Any parameters that are valid to be passed to the `openai.create` call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ChatAnyscale
- chat = ChatAnyscale(model_name="meta-llama/Llama-2-7b-chat-hf")
- """
-
- @property
- def _llm_type(self) -> str:
- """Return type of chat model."""
- return "anyscale-chat"
-
- @property
- def lc_secrets(self) -> dict[str, str]:
- return {"anyscale_api_key": "ANYSCALE_API_KEY"}
-
- anyscale_api_key: Optional[str] = None
- """AnyScale Endpoints API keys."""
- model_name: str = Field(default=DEFAULT_MODEL, alias="model")
- """Model name to use."""
- anyscale_api_base: str = Field(default=DEFAULT_API_BASE)
- """Base URL path for API requests,
- leave blank if not using a proxy or service emulator."""
- anyscale_proxy: Optional[str] = None
- """To support explicit proxy for Anyscale."""
- available_models: Optional[Set[str]] = None
- """Available models from Anyscale API."""
-
- @staticmethod
- def get_available_models(
- anyscale_api_key: Optional[str] = None,
- anyscale_api_base: str = DEFAULT_API_BASE,
- ) -> Set[str]:
- """Get available models from Anyscale API."""
- try:
- anyscale_api_key = anyscale_api_key or os.environ["ANYSCALE_API_KEY"]
- except KeyError as e:
- raise ValueError(
- "Anyscale API key must be passed as keyword argument or "
- "set in environment variable ANYSCALE_API_KEY.",
- ) from e
-
- models_url = f"{anyscale_api_base}/models"
- models_response = requests.get(
- models_url,
- headers={
- "Authorization": f"Bearer {anyscale_api_key}",
- },
- )
-
- if models_response.status_code != 200:
- raise ValueError(
- f"Error getting models from {models_url}: "
- f"{models_response.status_code}",
- )
-
- return {model["id"] for model in models_response.json()["data"]}
-
- @root_validator(pre=True)
- def validate_environment_override(cls, values: dict) -> dict:
- """Validate that api key and python package exists in environment."""
- values["openai_api_key"] = get_from_dict_or_env(
- values,
- "anyscale_api_key",
- "ANYSCALE_API_KEY",
- )
- values["openai_api_base"] = get_from_dict_or_env(
- values,
- "anyscale_api_base",
- "ANYSCALE_API_BASE",
- default=DEFAULT_API_BASE,
- )
- values["openai_proxy"] = get_from_dict_or_env(
- values,
- "anyscale_proxy",
- "ANYSCALE_PROXY",
- default="",
- )
- try:
- import openai
-
- except ImportError as e:
- raise ValueError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`.",
- ) from e
- try:
- values["client"] = openai.ChatCompletion
- except AttributeError as exc:
- raise ValueError(
- "`openai` has no `ChatCompletion` attribute, this is likely "
- "due to an old version of the openai package. Try upgrading it "
- "with `pip install --upgrade openai`.",
- ) from exc
-
- if "model_name" not in values.keys():
- values["model_name"] = DEFAULT_MODEL
-
- model_name = values["model_name"]
-
- available_models = cls.get_available_models(
- values["openai_api_key"],
- values["openai_api_base"],
- )
-
- if model_name not in available_models:
- raise ValueError(
- f"Model name {model_name} not found in available models: "
- f"{available_models}.",
- )
-
- values["available_models"] = available_models
-
- return values
-
- def _get_encoding_model(self) -> tuple[str, tiktoken.Encoding]:
- tiktoken_ = _import_tiktoken()
- if self.tiktoken_model_name is not None:
- model = self.tiktoken_model_name
- else:
- model = self.model_name
- # Returns the number of tokens used by a list of messages.
- try:
- encoding = tiktoken_.encoding_for_model("gpt-3.5-turbo-0301")
- except KeyError:
- logger.warning("Warning: model not found. Using cl100k_base encoding.")
- model = "cl100k_base"
- encoding = tiktoken_.get_encoding(model)
- return model, encoding
-
- def get_num_tokens_from_messages(self, messages: list[BaseMessage]) -> int:
- """Calculate num tokens with tiktoken package.
-
- Official documentation: https://github.com/openai/openai-cookbook/blob/
- main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb"""
- if sys.version_info[1] <= 7:
- return super().get_num_tokens_from_messages(messages)
- model, encoding = self._get_encoding_model()
- tokens_per_message = 3
- tokens_per_name = 1
- num_tokens = 0
- messages_dict = [convert_message_to_dict(m) for m in messages]
- for message in messages_dict:
- num_tokens += tokens_per_message
- for key, value in message.items():
- # Cast str(value) in case the message value is not a string
- # This occurs with function messages
- num_tokens += len(encoding.encode(str(value)))
- if key == "name":
- num_tokens += tokens_per_name
- # every reply is primed with assistant
- num_tokens += 3
- return num_tokens
diff --git a/commune/modules/model/chat_models/azure_openai.py b/commune/modules/model/chat_models/azure_openai.py
deleted file mode 100644
index c5090fd84..000000000
--- a/commune/modules/model/chat_models/azure_openai.py
+++ /dev/null
@@ -1,163 +0,0 @@
-"""Azure OpenAI chat wrapper."""
-from __future__ import annotations
-
-import logging
-from typing import Any, Dict, Mapping
-
-from langchain.chat_models.openai import ChatOpenAI
-from langchain.pydantic_v1 import root_validator
-from langchain.schema import ChatResult
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class AzureChatOpenAI(ChatOpenAI):
- """`Azure OpenAI` Chat Completion API.
-
- To use this class you
- must have a deployed model on Azure OpenAI. Use `deployment_name` in the
- constructor to refer to the "Model deployment name" in the Azure portal.
-
- In addition, you should have the ``openai`` python package installed, and the
- following environment variables set or passed in constructor in lower case:
- - ``OPENAI_API_TYPE`` (default: ``azure``)
- - ``OPENAI_API_KEY``
- - ``OPENAI_API_BASE``
- - ``OPENAI_API_VERSION``
- - ``OPENAI_PROXY``
-
- For example, if you have `gpt-35-turbo` deployed, with the deployment name
- `35-turbo-dev`, the constructor should look like:
-
- .. code-block:: python
-
- AzureChatOpenAI(
- deployment_name="35-turbo-dev",
- openai_api_version="2023-05-15",
- )
-
- Be aware the API version may change.
-
- You can also specify the version of the model using ``model_version`` constructor
- parameter, as Azure OpenAI doesn't return model version with the response.
-
- Default is empty. When you specify the version, it will be appended to the
- model name in the response. Setting correct version will help you to calculate the
- cost properly. Model version is not validated, so make sure you set it correctly
- to get the correct cost.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
- """
-
- deployment_name: str = ""
- model_version: str = ""
- openai_api_type: str = ""
- openai_api_base: str = ""
- openai_api_version: str = ""
- openai_api_key: str = ""
- openai_organization: str = ""
- openai_proxy: str = ""
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["openai_api_key"] = get_from_dict_or_env(
- values,
- "openai_api_key",
- "OPENAI_API_KEY",
- )
- values["openai_api_base"] = get_from_dict_or_env(
- values,
- "openai_api_base",
- "OPENAI_API_BASE",
- )
- values["openai_api_version"] = get_from_dict_or_env(
- values,
- "openai_api_version",
- "OPENAI_API_VERSION",
- )
- values["openai_api_type"] = get_from_dict_or_env(
- values, "openai_api_type", "OPENAI_API_TYPE", default="azure"
- )
- values["openai_organization"] = get_from_dict_or_env(
- values,
- "openai_organization",
- "OPENAI_ORGANIZATION",
- default="",
- )
- values["openai_proxy"] = get_from_dict_or_env(
- values,
- "openai_proxy",
- "OPENAI_PROXY",
- default="",
- )
- try:
- import openai
-
- except ImportError:
- raise ImportError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`."
- )
- try:
- values["client"] = openai.ChatCompletion
- except AttributeError:
- raise ValueError(
- "`openai` has no `ChatCompletion` attribute, this is likely "
- "due to an old version of the openai package. Try upgrading it "
- "with `pip install --upgrade openai`."
- )
- if values["n"] < 1:
- raise ValueError("n must be at least 1.")
- if values["n"] > 1 and values["streaming"]:
- raise ValueError("n must be 1 when streaming.")
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- return {
- **super()._default_params,
- "engine": self.deployment_name,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**self._default_params}
-
- @property
- def _client_params(self) -> Dict[str, Any]:
- """Get the config params used for the openai client."""
- return {
- **super()._client_params,
- "api_type": self.openai_api_type,
- "api_version": self.openai_api_version,
- }
-
- @property
- def _llm_type(self) -> str:
- return "azure-openai-chat"
-
- def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
- for res in response["choices"]:
- if res.get("finish_reason", None) == "content_filter":
- raise ValueError(
- "Azure has not provided the response due to a content filter "
- "being triggered"
- )
- chat_result = super()._create_chat_result(response)
-
- if "model" in response:
- model = response["model"]
- if self.model_version:
- model = f"{model}-{self.model_version}"
-
- if chat_result.llm_output is not None and isinstance(
- chat_result.llm_output, dict
- ):
- chat_result.llm_output["model_name"] = model
-
- return chat_result
diff --git a/commune/modules/model/chat_models/azureml_endpoint.py b/commune/modules/model/chat_models/azureml_endpoint.py
deleted file mode 100644
index 9cd57fbcf..000000000
--- a/commune/modules/model/chat_models/azureml_endpoint.py
+++ /dev/null
@@ -1,150 +0,0 @@
-import json
-from typing import Any, Dict, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.chat_models.base import SimpleChatModel
-from langchain.llms.azureml_endpoint import AzureMLEndpointClient, ContentFormatterBase
-from langchain.pydantic_v1 import validator
-from langchain.schema.messages import (
- AIMessage,
- BaseMessage,
- ChatMessage,
- HumanMessage,
- SystemMessage,
-)
-from langchain.utils import get_from_dict_or_env
-
-
-class LlamaContentFormatter(ContentFormatterBase):
- """Content formatter for `LLaMA`."""
-
- SUPPORTED_ROLES: List[str] = ["user", "assistant", "system"]
-
- @staticmethod
- def _convert_message_to_dict(message: BaseMessage) -> Dict:
- """Converts message to a dict according to role"""
- if isinstance(message, HumanMessage):
- return {"role": "user", "content": message.content}
- elif isinstance(message, AIMessage):
- return {"role": "assistant", "content": message.content}
- elif isinstance(message, SystemMessage):
- return {"role": "system", "content": message.content}
- elif (
- isinstance(message, ChatMessage)
- and message.role in LlamaContentFormatter.SUPPORTED_ROLES
- ):
- return {"role": message.role, "content": message.content}
- else:
- supported = ",".join(
- [role for role in LlamaContentFormatter.SUPPORTED_ROLES]
- )
- raise ValueError(
- f"""Received unsupported role.
- Supported roles for the LLaMa Foundation Model: {supported}"""
- )
-
- def _format_request_payload(
- self, messages: List[BaseMessage], model_kwargs: Dict
- ) -> bytes:
- chat_messages = [
- LlamaContentFormatter._convert_message_to_dict(message)
- for message in messages
- ]
- prompt = json.dumps(
- {"input_data": {"input_string": chat_messages, "parameters": model_kwargs}}
- )
- return self.format_request_payload(prompt=prompt, model_kwargs=model_kwargs)
-
- def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
- """Formats the request according the the chosen api"""
- return str.encode(prompt)
-
- def format_response_payload(self, output: bytes) -> str:
- """Formats response"""
- return json.loads(output)["output"]
-
-
-class AzureMLChatOnlineEndpoint(SimpleChatModel):
- """`AzureML` Chat models API.
-
- Example:
- .. code-block:: python
-
- azure_chat = AzureMLChatOnlineEndpoint(
- endpoint_url="https://..inference.ml.azure.com/score",
- endpoint_api_key="my-api-key",
- content_formatter=content_formatter,
- )
- """
-
- endpoint_url: str = ""
- """URL of pre-existing Endpoint. Should be passed to constructor or specified as
- env var `AZUREML_ENDPOINT_URL`."""
-
- endpoint_api_key: str = ""
- """Authentication Key for Endpoint. Should be passed to constructor or specified as
- env var `AZUREML_ENDPOINT_API_KEY`."""
-
- http_client: Any = None #: :meta private:
-
- content_formatter: Any = None
- """The content formatter that provides an input and output
- transform function to handle formats between the LLM and
- the endpoint"""
-
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
-
- @validator("http_client", always=True, allow_reuse=True)
- @classmethod
- def validate_client(cls, field_value: Any, values: Dict) -> AzureMLEndpointClient:
- """Validate that api key and python package exists in environment."""
- endpoint_key = get_from_dict_or_env(
- values, "endpoint_api_key", "AZUREML_ENDPOINT_API_KEY"
- )
- endpoint_url = get_from_dict_or_env(
- values, "endpoint_url", "AZUREML_ENDPOINT_URL"
- )
- http_client = AzureMLEndpointClient(endpoint_url, endpoint_key)
- return http_client
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "azureml_chat_endpoint"
-
- def _call(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to an AzureML Managed Online endpoint.
- Args:
- messages: The messages in the conversation with the chat model.
- stop: Optional list of stop words to use when generating.
- Returns:
- The string generated by the model.
- Example:
- .. code-block:: python
- response = azureml_model("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
-
- request_payload = self.content_formatter._format_request_payload(
- messages, _model_kwargs
- )
- response_payload = self.http_client.call(request_payload, **kwargs)
- generated_text = self.content_formatter.format_response_payload(
- response_payload
- )
- return generated_text
diff --git a/commune/modules/model/chat_models/base.py b/commune/modules/model/chat_models/base.py
deleted file mode 100644
index 2d0db37c0..000000000
--- a/commune/modules/model/chat_models/base.py
+++ /dev/null
@@ -1,680 +0,0 @@
-import asyncio
-import inspect
-import warnings
-from abc import ABC, abstractmethod
-from functools import partial
-from typing import (
- Any,
- AsyncIterator,
- Dict,
- Iterator,
- List,
- Optional,
- Sequence,
- cast,
-)
-
-import langchain
-from langchain.callbacks.base import BaseCallbackManager
-from langchain.callbacks.manager import (
- AsyncCallbackManager,
- AsyncCallbackManagerForLLMRun,
- CallbackManager,
- CallbackManagerForLLMRun,
- Callbacks,
-)
-from langchain.load.dump import dumpd, dumps
-from langchain.prompts.base import StringPromptValue
-from langchain.prompts.chat import ChatPromptValue
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import (
- ChatGeneration,
- ChatResult,
- LLMResult,
- PromptValue,
- RunInfo,
-)
-from langchain.schema.language_model import BaseLanguageModel, LanguageModelInput
-from langchain.schema.messages import (
- AIMessage,
- BaseMessage,
- BaseMessageChunk,
- HumanMessage,
-)
-from langchain.schema.output import ChatGenerationChunk
-from langchain.schema.runnable import RunnableConfig
-
-
-def _get_verbosity() -> bool:
- return langchain.verbose
-
-
-class BaseChatModel(BaseLanguageModel[BaseMessageChunk], ABC):
- """Base class for Chat models."""
-
- cache: Optional[bool] = None
- """Whether to cache the response."""
- verbose: bool = Field(default_factory=_get_verbosity)
- """Whether to print out response text."""
- callbacks: Callbacks = Field(default=None, exclude=True)
- """Callbacks to add to the run trace."""
- callback_manager: Optional[BaseCallbackManager] = Field(default=None, exclude=True)
- """Callback manager to add to the run trace."""
- tags: Optional[List[str]] = Field(default=None, exclude=True)
- """Tags to add to the run trace."""
- metadata: Optional[Dict[str, Any]] = Field(default=None, exclude=True)
- """Metadata to add to the run trace."""
-
- @root_validator()
- def raise_deprecation(cls, values: Dict) -> Dict:
- """Raise deprecation warning if callback_manager is used."""
- if values.get("callback_manager") is not None:
- warnings.warn(
- "callback_manager is deprecated. Please use callbacks instead.",
- DeprecationWarning,
- )
- values["callbacks"] = values.pop("callback_manager", None)
- return values
-
- class Config:
- """Configuration for this pydantic object."""
-
- arbitrary_types_allowed = True
-
- # --- Runnable methods ---
-
- def _convert_input(self, input: LanguageModelInput) -> PromptValue:
- if isinstance(input, PromptValue):
- return input
- elif isinstance(input, str):
- return StringPromptValue(text=input)
- elif isinstance(input, list):
- return ChatPromptValue(messages=input)
- else:
- raise ValueError(
- f"Invalid input type {type(input)}. "
- "Must be a PromptValue, str, or list of BaseMessages."
- )
-
- def invoke(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> BaseMessageChunk:
- config = config or {}
- return cast(
- BaseMessageChunk,
- cast(
- ChatGeneration,
- self.generate_prompt(
- [self._convert_input(input)],
- stop=stop,
- callbacks=config.get("callbacks"),
- tags=config.get("tags"),
- metadata=config.get("metadata"),
- **kwargs,
- ).generations[0][0],
- ).message,
- )
-
- async def ainvoke(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> BaseMessageChunk:
- if type(self)._agenerate == BaseChatModel._agenerate:
- # model doesn't implement async generation, so use default implementation
- return await asyncio.get_running_loop().run_in_executor(
- None, partial(self.invoke, input, config, stop=stop, **kwargs)
- )
-
- config = config or {}
- llm_result = await self.agenerate_prompt(
- [self._convert_input(input)],
- stop=stop,
- callbacks=config.get("callbacks"),
- tags=config.get("tags"),
- metadata=config.get("metadata"),
- **kwargs,
- )
- return cast(
- BaseMessageChunk, cast(ChatGeneration, llm_result.generations[0][0]).message
- )
-
- def stream(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> Iterator[BaseMessageChunk]:
- if type(self)._stream == BaseChatModel._stream:
- # model doesn't implement streaming, so use default implementation
- yield self.invoke(input, config=config, stop=stop, **kwargs)
- else:
- config = config or {}
- messages = self._convert_input(input).to_messages()
- params = self._get_invocation_params(stop=stop, **kwargs)
- options = {"stop": stop, **kwargs}
- callback_manager = CallbackManager.configure(
- config.get("callbacks"),
- self.callbacks,
- self.verbose,
- config.get("tags"),
- self.tags,
- config.get("metadata"),
- self.metadata,
- )
- (run_manager,) = callback_manager.on_chat_model_start(
- dumpd(self), [messages], invocation_params=params, options=options
- )
- try:
- generation: Optional[ChatGenerationChunk] = None
- for chunk in self._stream(
- messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- yield chunk.message
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- except (KeyboardInterrupt, Exception) as e:
- run_manager.on_llm_error(e)
- raise e
- else:
- run_manager.on_llm_end(
- LLMResult(generations=[[generation]]),
- )
-
- async def astream(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> AsyncIterator[BaseMessageChunk]:
- if type(self)._astream == BaseChatModel._astream:
- # model doesn't implement streaming, so use default implementation
- yield self.invoke(input, config=config, stop=stop, **kwargs)
- else:
- config = config or {}
- messages = self._convert_input(input).to_messages()
- params = self._get_invocation_params(stop=stop, **kwargs)
- options = {"stop": stop, **kwargs}
- callback_manager = AsyncCallbackManager.configure(
- config.get("callbacks"),
- self.callbacks,
- self.verbose,
- config.get("tags"),
- self.tags,
- config.get("metadata"),
- self.metadata,
- )
- (run_manager,) = await callback_manager.on_chat_model_start(
- dumpd(self), [messages], invocation_params=params, options=options
- )
- try:
- generation: Optional[ChatGenerationChunk] = None
- async for chunk in self._astream(
- messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- yield chunk.message
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- except (KeyboardInterrupt, Exception) as e:
- await run_manager.on_llm_error(e)
- raise e
- else:
- await run_manager.on_llm_end(
- LLMResult(generations=[[generation]]),
- )
-
- # --- Custom methods ---
-
- def _combine_llm_outputs(self, llm_outputs: List[Optional[dict]]) -> dict:
- return {}
-
- def _get_invocation_params(
- self,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> dict:
- params = self.dict()
- params["stop"] = stop
- return {**params, **kwargs}
-
- def _get_llm_string(self, stop: Optional[List[str]] = None, **kwargs: Any) -> str:
- if self.lc_serializable:
- params = {**kwargs, **{"stop": stop}}
- param_string = str(sorted([(k, v) for k, v in params.items()]))
- llm_string = dumps(self)
- return llm_string + "---" + param_string
- else:
- params = self._get_invocation_params(stop=stop, **kwargs)
- params = {**params, **kwargs}
- return str(sorted([(k, v) for k, v in params.items()]))
-
- def generate(
- self,
- messages: List[List[BaseMessage]],
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- *,
- tags: Optional[List[str]] = None,
- metadata: Optional[Dict[str, Any]] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Top Level call"""
- params = self._get_invocation_params(stop=stop, **kwargs)
- options = {"stop": stop}
-
- callback_manager = CallbackManager.configure(
- callbacks,
- self.callbacks,
- self.verbose,
- tags,
- self.tags,
- metadata,
- self.metadata,
- )
- run_managers = callback_manager.on_chat_model_start(
- dumpd(self), messages, invocation_params=params, options=options
- )
- results = []
- for i, m in enumerate(messages):
- try:
- results.append(
- self._generate_with_cache(
- m,
- stop=stop,
- run_manager=run_managers[i] if run_managers else None,
- **kwargs,
- )
- )
- except (KeyboardInterrupt, Exception) as e:
- if run_managers:
- run_managers[i].on_llm_error(e)
- raise e
- flattened_outputs = [
- LLMResult(generations=[res.generations], llm_output=res.llm_output)
- for res in results
- ]
- llm_output = self._combine_llm_outputs([res.llm_output for res in results])
- generations = [res.generations for res in results]
- output = LLMResult(generations=generations, llm_output=llm_output)
- if run_managers:
- run_infos = []
- for manager, flattened_output in zip(run_managers, flattened_outputs):
- manager.on_llm_end(flattened_output)
- run_infos.append(RunInfo(run_id=manager.run_id))
- output.run = run_infos
- return output
-
- async def agenerate(
- self,
- messages: List[List[BaseMessage]],
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- *,
- tags: Optional[List[str]] = None,
- metadata: Optional[Dict[str, Any]] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Top Level call"""
- params = self._get_invocation_params(stop=stop, **kwargs)
- options = {"stop": stop}
-
- callback_manager = AsyncCallbackManager.configure(
- callbacks,
- self.callbacks,
- self.verbose,
- tags,
- self.tags,
- metadata,
- self.metadata,
- )
-
- run_managers = await callback_manager.on_chat_model_start(
- dumpd(self), messages, invocation_params=params, options=options
- )
-
- results = await asyncio.gather(
- *[
- self._agenerate_with_cache(
- m,
- stop=stop,
- run_manager=run_managers[i] if run_managers else None,
- **kwargs,
- )
- for i, m in enumerate(messages)
- ],
- return_exceptions=True,
- )
- exceptions = []
- for i, res in enumerate(results):
- if isinstance(res, Exception):
- if run_managers:
- await run_managers[i].on_llm_error(res)
- exceptions.append(res)
- if exceptions:
- if run_managers:
- await asyncio.gather(
- *[
- run_manager.on_llm_end(
- LLMResult(
- generations=[res.generations], llm_output=res.llm_output
- )
- )
- for run_manager, res in zip(run_managers, results)
- if not isinstance(res, Exception)
- ]
- )
- raise exceptions[0]
- flattened_outputs = [
- LLMResult(generations=[res.generations], llm_output=res.llm_output)
- for res in results
- ]
- llm_output = self._combine_llm_outputs([res.llm_output for res in results])
- generations = [res.generations for res in results]
- output = LLMResult(generations=generations, llm_output=llm_output)
- await asyncio.gather(
- *[
- run_manager.on_llm_end(flattened_output)
- for run_manager, flattened_output in zip(
- run_managers, flattened_outputs
- )
- ]
- )
- if run_managers:
- output.run = [
- RunInfo(run_id=run_manager.run_id) for run_manager in run_managers
- ]
- return output
-
- def generate_prompt(
- self,
- prompts: List[PromptValue],
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- **kwargs: Any,
- ) -> LLMResult:
- prompt_messages = [p.to_messages() for p in prompts]
- return self.generate(prompt_messages, stop=stop, callbacks=callbacks, **kwargs)
-
- async def agenerate_prompt(
- self,
- prompts: List[PromptValue],
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- **kwargs: Any,
- ) -> LLMResult:
- prompt_messages = [p.to_messages() for p in prompts]
- return await self.agenerate(
- prompt_messages, stop=stop, callbacks=callbacks, **kwargs
- )
-
- def _generate_with_cache(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- new_arg_supported = inspect.signature(self._generate).parameters.get(
- "run_manager"
- )
- disregard_cache = self.cache is not None and not self.cache
- if langchain.llm_cache is None or disregard_cache:
- # This happens when langchain.cache is None, but self.cache is True
- if self.cache is not None and self.cache:
- raise ValueError(
- "Asked to cache, but no cache found at `langchain.cache`."
- )
- if new_arg_supported:
- return self._generate(
- messages, stop=stop, run_manager=run_manager, **kwargs
- )
- else:
- return self._generate(messages, stop=stop, **kwargs)
- else:
- llm_string = self._get_llm_string(stop=stop, **kwargs)
- prompt = dumps(messages)
- cache_val = langchain.llm_cache.lookup(prompt, llm_string)
- if isinstance(cache_val, list):
- return ChatResult(generations=cache_val)
- else:
- if new_arg_supported:
- result = self._generate(
- messages, stop=stop, run_manager=run_manager, **kwargs
- )
- else:
- result = self._generate(messages, stop=stop, **kwargs)
- langchain.llm_cache.update(prompt, llm_string, result.generations)
- return result
-
- async def _agenerate_with_cache(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- new_arg_supported = inspect.signature(self._agenerate).parameters.get(
- "run_manager"
- )
- disregard_cache = self.cache is not None and not self.cache
- if langchain.llm_cache is None or disregard_cache:
- # This happens when langchain.cache is None, but self.cache is True
- if self.cache is not None and self.cache:
- raise ValueError(
- "Asked to cache, but no cache found at `langchain.cache`."
- )
- if new_arg_supported:
- return await self._agenerate(
- messages, stop=stop, run_manager=run_manager, **kwargs
- )
- else:
- return await self._agenerate(messages, stop=stop, **kwargs)
- else:
- llm_string = self._get_llm_string(stop=stop, **kwargs)
- prompt = dumps(messages)
- cache_val = langchain.llm_cache.lookup(prompt, llm_string)
- if isinstance(cache_val, list):
- return ChatResult(generations=cache_val)
- else:
- if new_arg_supported:
- result = await self._agenerate(
- messages, stop=stop, run_manager=run_manager, **kwargs
- )
- else:
- result = await self._agenerate(messages, stop=stop, **kwargs)
- langchain.llm_cache.update(prompt, llm_string, result.generations)
- return result
-
- @abstractmethod
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- """Top Level call"""
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- """Top Level call"""
- raise NotImplementedError()
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- raise NotImplementedError()
-
- def _astream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- raise NotImplementedError()
-
- def __call__(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- **kwargs: Any,
- ) -> BaseMessage:
- generation = self.generate(
- [messages], stop=stop, callbacks=callbacks, **kwargs
- ).generations[0][0]
- if isinstance(generation, ChatGeneration):
- return generation.message
- else:
- raise ValueError("Unexpected generation type")
-
- async def _call_async(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- **kwargs: Any,
- ) -> BaseMessage:
- result = await self.agenerate(
- [messages], stop=stop, callbacks=callbacks, **kwargs
- )
- generation = result.generations[0][0]
- if isinstance(generation, ChatGeneration):
- return generation.message
- else:
- raise ValueError("Unexpected generation type")
-
- def call_as_llm(
- self, message: str, stop: Optional[List[str]] = None, **kwargs: Any
- ) -> str:
- return self.predict(message, stop=stop, **kwargs)
-
- def predict(
- self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any
- ) -> str:
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- result = self([HumanMessage(content=text)], stop=_stop, **kwargs)
- return result.content
-
- def predict_messages(
- self,
- messages: List[BaseMessage],
- *,
- stop: Optional[Sequence[str]] = None,
- **kwargs: Any,
- ) -> BaseMessage:
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- return self(messages, stop=_stop, **kwargs)
-
- async def apredict(
- self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any
- ) -> str:
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- result = await self._call_async(
- [HumanMessage(content=text)], stop=_stop, **kwargs
- )
- return result.content
-
- async def apredict_messages(
- self,
- messages: List[BaseMessage],
- *,
- stop: Optional[Sequence[str]] = None,
- **kwargs: Any,
- ) -> BaseMessage:
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- return await self._call_async(messages, stop=_stop, **kwargs)
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {}
-
- @property
- @abstractmethod
- def _llm_type(self) -> str:
- """Return type of chat model."""
-
- def dict(self, **kwargs: Any) -> Dict:
- """Return a dictionary of the LLM."""
- starter_dict = dict(self._identifying_params)
- starter_dict["_type"] = self._llm_type
- return starter_dict
-
-
-class SimpleChatModel(BaseChatModel):
- """Simple Chat Model."""
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- output_str = self._call(messages, stop=stop, run_manager=run_manager, **kwargs)
- message = AIMessage(content=output_str)
- generation = ChatGeneration(message=message)
- return ChatResult(generations=[generation])
-
- @abstractmethod
- def _call(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Simpler interface."""
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- func = partial(
- self._generate, messages, stop=stop, run_manager=run_manager, **kwargs
- )
- return await asyncio.get_event_loop().run_in_executor(None, func)
diff --git a/commune/modules/model/chat_models/ernie.py b/commune/modules/model/chat_models/ernie.py
deleted file mode 100644
index 1ccecf36f..000000000
--- a/commune/modules/model/chat_models/ernie.py
+++ /dev/null
@@ -1,162 +0,0 @@
-import logging
-import threading
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.chat_models.base import BaseChatModel
-from langchain.pydantic_v1 import root_validator
-from langchain.schema import (
- AIMessage,
- BaseMessage,
- ChatGeneration,
- ChatMessage,
- ChatResult,
- HumanMessage,
-)
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-def _convert_message_to_dict(message: BaseMessage) -> dict:
- if isinstance(message, ChatMessage):
- message_dict = {"role": message.role, "content": message.content}
- elif isinstance(message, HumanMessage):
- message_dict = {"role": "user", "content": message.content}
- elif isinstance(message, AIMessage):
- message_dict = {"role": "assistant", "content": message.content}
- else:
- raise ValueError(f"Got unknown type {message}")
- return message_dict
-
-
-class ErnieBotChat(BaseChatModel):
- """`ERNIE-Bot` large language model.
-
- ERNIE-Bot is a large language model developed by Baidu,
- covering a huge amount of Chinese data.
-
- To use, you should have the `ernie_client_id` and `ernie_client_secret` set,
- or set the environment variable `ERNIE_CLIENT_ID` and `ERNIE_CLIENT_SECRET`.
-
- Note:
- access_token will be automatically generated based on client_id and client_secret,
- and will be regenerated after expiration (30 days).
-
- Default model is `ERNIE-Bot-turbo`,
- currently supported models are `ERNIE-Bot-turbo`, `ERNIE-Bot`
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ErnieBotChat
- chat = ErnieBotChat(model_name='ERNIE-Bot')
-
- """
-
- ernie_client_id: Optional[str] = None
- ernie_client_secret: Optional[str] = None
- access_token: Optional[str] = None
-
- model_name: str = "ERNIE-Bot-turbo"
-
- streaming: Optional[bool] = False
- top_p: Optional[float] = 0.8
- temperature: Optional[float] = 0.95
- penalty_score: Optional[float] = 1
-
- _lock = threading.Lock()
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- values["ernie_client_id"] = get_from_dict_or_env(
- values,
- "ernie_client_id",
- "ERNIE_CLIENT_ID",
- )
- values["ernie_client_secret"] = get_from_dict_or_env(
- values,
- "ernie_client_secret",
- "ERNIE_CLIENT_SECRET",
- )
- return values
-
- def _chat(self, payload: object) -> dict:
- base_url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat"
- if self.model_name == "ERNIE-Bot-turbo":
- url = f"{base_url}/eb-instant"
- elif self.model_name == "ERNIE-Bot":
- url = f"{base_url}/completions"
- else:
- raise ValueError(f"Got unknown model_name {self.model_name}")
- resp = requests.post(
- url,
- headers={
- "Content-Type": "application/json",
- },
- params={"access_token": self.access_token},
- json=payload,
- )
- return resp.json()
-
- def _refresh_access_token_with_lock(self) -> None:
- with self._lock:
- logger.debug("Refreshing access token")
- base_url: str = "https://aip.baidubce.com/oauth/2.0/token"
- resp = requests.post(
- base_url,
- headers={
- "Content-Type": "application/json",
- "Accept": "application/json",
- },
- params={
- "grant_type": "client_credentials",
- "client_id": self.ernie_client_id,
- "client_secret": self.ernie_client_secret,
- },
- )
- self.access_token = str(resp.json().get("access_token"))
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if self.streaming:
- raise ValueError("`streaming` option currently unsupported.")
-
- if not self.access_token:
- self._refresh_access_token_with_lock()
- payload = {
- "messages": [_convert_message_to_dict(m) for m in messages],
- "top_p": self.top_p,
- "temperature": self.temperature,
- "penalty_score": self.penalty_score,
- **kwargs,
- }
- logger.debug(f"Payload for ernie api is {payload}")
- resp = self._chat(payload)
- if resp.get("error_code"):
- if resp.get("error_code") == 111:
- logger.debug("access_token expired, refresh it")
- self._refresh_access_token_with_lock()
- resp = self._chat(payload)
- else:
- raise ValueError(f"Error from ErnieChat api response: {resp}")
- return self._create_chat_result(resp)
-
- def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
- generations = [
- ChatGeneration(message=AIMessage(content=response.get("result")))
- ]
- token_usage = response.get("usage", {})
- llm_output = {"token_usage": token_usage, "model_name": self.model_name}
- return ChatResult(generations=generations, llm_output=llm_output)
-
- @property
- def _llm_type(self) -> str:
- return "ernie-bot-chat"
diff --git a/commune/modules/model/chat_models/fake.py b/commune/modules/model/chat_models/fake.py
deleted file mode 100644
index 1fe54fef6..000000000
--- a/commune/modules/model/chat_models/fake.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""Fake ChatModel for testing purposes."""
-import asyncio
-import time
-from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Union
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import SimpleChatModel
-from langchain.schema.messages import AIMessageChunk, BaseMessage
-from langchain.schema.output import ChatGenerationChunk
-
-
-class FakeListChatModel(SimpleChatModel):
- """Fake ChatModel for testing purposes."""
-
- responses: List
- sleep: Optional[float] = None
- i: int = 0
-
- @property
- def _llm_type(self) -> str:
- return "fake-list-chat-model"
-
- def _call(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """First try to lookup in queries, else return 'foo' or 'bar'."""
- response = self.responses[self.i]
- if self.i < len(self.responses) - 1:
- self.i += 1
- else:
- self.i = 0
- return response
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Union[List[str], None] = None,
- run_manager: Union[CallbackManagerForLLMRun, None] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- response = self.responses[self.i]
- if self.i < len(self.responses) - 1:
- self.i += 1
- else:
- self.i = 0
- for c in response:
- if self.sleep is not None:
- time.sleep(self.sleep)
- yield ChatGenerationChunk(message=AIMessageChunk(content=c))
-
- async def _astream(
- self,
- messages: List[BaseMessage],
- stop: Union[List[str], None] = None,
- run_manager: Union[AsyncCallbackManagerForLLMRun, None] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- response = self.responses[self.i]
- if self.i < len(self.responses) - 1:
- self.i += 1
- else:
- self.i = 0
- for c in response:
- if self.sleep is not None:
- await asyncio.sleep(self.sleep)
- yield ChatGenerationChunk(message=AIMessageChunk(content=c))
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- return {"responses": self.responses}
diff --git a/commune/modules/model/chat_models/google_palm.py b/commune/modules/model/chat_models/google_palm.py
deleted file mode 100644
index cc7c288f8..000000000
--- a/commune/modules/model/chat_models/google_palm.py
+++ /dev/null
@@ -1,336 +0,0 @@
-"""Wrapper around Google's PaLM Chat API."""
-from __future__ import annotations
-
-import logging
-from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
-
-from tenacity import (
- before_sleep_log,
- retry,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.pydantic_v1 import BaseModel, root_validator
-from langchain.schema import (
- ChatGeneration,
- ChatResult,
-)
-from langchain.schema.messages import (
- AIMessage,
- BaseMessage,
- ChatMessage,
- HumanMessage,
- SystemMessage,
-)
-from langchain.utils import get_from_dict_or_env
-
-if TYPE_CHECKING:
- import google.generativeai as genai
-
-logger = logging.getLogger(__name__)
-
-
-class ChatGooglePalmError(Exception):
- """Error with the `Google PaLM` API."""
-
-
-def _truncate_at_stop_tokens(
- text: str,
- stop: Optional[List[str]],
-) -> str:
- """Truncates text at the earliest stop token found."""
- if stop is None:
- return text
-
- for stop_token in stop:
- stop_token_idx = text.find(stop_token)
- if stop_token_idx != -1:
- text = text[:stop_token_idx]
- return text
-
-
-def _response_to_result(
- response: genai.types.ChatResponse,
- stop: Optional[List[str]],
-) -> ChatResult:
- """Converts a PaLM API response into a LangChain ChatResult."""
- if not response.candidates:
- raise ChatGooglePalmError("ChatResponse must have at least one candidate.")
-
- generations: List[ChatGeneration] = []
- for candidate in response.candidates:
- author = candidate.get("author")
- if author is None:
- raise ChatGooglePalmError(f"ChatResponse must have an author: {candidate}")
-
- content = _truncate_at_stop_tokens(candidate.get("content", ""), stop)
- if content is None:
- raise ChatGooglePalmError(f"ChatResponse must have a content: {candidate}")
-
- if author == "ai":
- generations.append(
- ChatGeneration(text=content, message=AIMessage(content=content))
- )
- elif author == "human":
- generations.append(
- ChatGeneration(
- text=content,
- message=HumanMessage(content=content),
- )
- )
- else:
- generations.append(
- ChatGeneration(
- text=content,
- message=ChatMessage(role=author, content=content),
- )
- )
-
- return ChatResult(generations=generations)
-
-
-def _messages_to_prompt_dict(
- input_messages: List[BaseMessage],
-) -> genai.types.MessagePromptDict:
- """Converts a list of LangChain messages into a PaLM API MessagePrompt structure."""
- import google.generativeai as genai
-
- context: str = ""
- examples: List[genai.types.MessageDict] = []
- messages: List[genai.types.MessageDict] = []
-
- remaining = list(enumerate(input_messages))
-
- while remaining:
- index, input_message = remaining.pop(0)
-
- if isinstance(input_message, SystemMessage):
- if index != 0:
- raise ChatGooglePalmError("System message must be first input message.")
- context = input_message.content
- elif isinstance(input_message, HumanMessage) and input_message.example:
- if messages:
- raise ChatGooglePalmError(
- "Message examples must come before other messages."
- )
- _, next_input_message = remaining.pop(0)
- if isinstance(next_input_message, AIMessage) and next_input_message.example:
- examples.extend(
- [
- genai.types.MessageDict(
- author="human", content=input_message.content
- ),
- genai.types.MessageDict(
- author="ai", content=next_input_message.content
- ),
- ]
- )
- else:
- raise ChatGooglePalmError(
- "Human example message must be immediately followed by an "
- " AI example response."
- )
- elif isinstance(input_message, AIMessage) and input_message.example:
- raise ChatGooglePalmError(
- "AI example message must be immediately preceded by a Human "
- "example message."
- )
- elif isinstance(input_message, AIMessage):
- messages.append(
- genai.types.MessageDict(author="ai", content=input_message.content)
- )
- elif isinstance(input_message, HumanMessage):
- messages.append(
- genai.types.MessageDict(author="human", content=input_message.content)
- )
- elif isinstance(input_message, ChatMessage):
- messages.append(
- genai.types.MessageDict(
- author=input_message.role, content=input_message.content
- )
- )
- else:
- raise ChatGooglePalmError(
- "Messages without an explicit role not supported by PaLM API."
- )
-
- return genai.types.MessagePromptDict(
- context=context,
- examples=examples,
- messages=messages,
- )
-
-
-def _create_retry_decorator() -> Callable[[Any], Any]:
- """Returns a tenacity retry decorator, preconfigured to handle PaLM exceptions"""
- import google.api_core.exceptions
-
- multiplier = 2
- min_seconds = 1
- max_seconds = 60
- max_retries = 10
-
- return retry(
- reraise=True,
- stop=stop_after_attempt(max_retries),
- wait=wait_exponential(multiplier=multiplier, min=min_seconds, max=max_seconds),
- retry=(
- retry_if_exception_type(google.api_core.exceptions.ResourceExhausted)
- | retry_if_exception_type(google.api_core.exceptions.ServiceUnavailable)
- | retry_if_exception_type(google.api_core.exceptions.GoogleAPIError)
- ),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
-
-def chat_with_retry(llm: ChatGooglePalm, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator()
-
- @retry_decorator
- def _chat_with_retry(**kwargs: Any) -> Any:
- return llm.client.chat(**kwargs)
-
- return _chat_with_retry(**kwargs)
-
-
-async def achat_with_retry(llm: ChatGooglePalm, **kwargs: Any) -> Any:
- """Use tenacity to retry the async completion call."""
- retry_decorator = _create_retry_decorator()
-
- @retry_decorator
- async def _achat_with_retry(**kwargs: Any) -> Any:
- # Use OpenAI's async api https://github.com/openai/openai-python#async-api
- return await llm.client.chat_async(**kwargs)
-
- return await _achat_with_retry(**kwargs)
-
-
-class ChatGooglePalm(BaseChatModel, BaseModel):
- """`Google PaLM` Chat models API.
-
- To use you must have the google.generativeai Python package installed and
- either:
-
- 1. The ``GOOGLE_API_KEY``` environment variable set with your API key, or
- 2. Pass your API key using the google_api_key kwarg to the ChatGoogle
- constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ChatGooglePalm
- chat = ChatGooglePalm()
-
- """
-
- client: Any #: :meta private:
- model_name: str = "models/chat-bison-001"
- """Model name to use."""
- google_api_key: Optional[str] = None
- temperature: Optional[float] = None
- """Run inference with this temperature. Must by in the closed
- interval [0.0, 1.0]."""
- top_p: Optional[float] = None
- """Decode using nucleus sampling: consider the smallest set of tokens whose
- probability sum is at least top_p. Must be in the closed interval [0.0, 1.0]."""
- top_k: Optional[int] = None
- """Decode using top-k sampling: consider the set of top_k most probable tokens.
- Must be positive."""
- n: int = 1
- """Number of chat completions to generate for each prompt. Note that the API may
- not return the full n completions if duplicates are generated."""
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate api key, python package exists, temperature, top_p, and top_k."""
- google_api_key = get_from_dict_or_env(
- values, "google_api_key", "GOOGLE_API_KEY"
- )
- try:
- import google.generativeai as genai
-
- genai.configure(api_key=google_api_key)
- except ImportError:
- raise ChatGooglePalmError(
- "Could not import google.generativeai python package. "
- "Please install it with `pip install google-generativeai`"
- )
-
- values["client"] = genai
-
- if values["temperature"] is not None and not 0 <= values["temperature"] <= 1:
- raise ValueError("temperature must be in the range [0.0, 1.0]")
-
- if values["top_p"] is not None and not 0 <= values["top_p"] <= 1:
- raise ValueError("top_p must be in the range [0.0, 1.0]")
-
- if values["top_k"] is not None and values["top_k"] <= 0:
- raise ValueError("top_k must be positive")
-
- return values
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- prompt = _messages_to_prompt_dict(messages)
-
- response: genai.types.ChatResponse = chat_with_retry(
- self,
- model=self.model_name,
- prompt=prompt,
- temperature=self.temperature,
- top_p=self.top_p,
- top_k=self.top_k,
- candidate_count=self.n,
- **kwargs,
- )
-
- return _response_to_result(response, stop)
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- prompt = _messages_to_prompt_dict(messages)
-
- response: genai.types.ChatResponse = await achat_with_retry(
- self,
- model=self.model_name,
- prompt=prompt,
- temperature=self.temperature,
- top_p=self.top_p,
- top_k=self.top_k,
- candidate_count=self.n,
- )
-
- return _response_to_result(response, stop)
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {
- "model_name": self.model_name,
- "temperature": self.temperature,
- "top_p": self.top_p,
- "top_k": self.top_k,
- "n": self.n,
- }
-
- @property
- def _llm_type(self) -> str:
- return "google-palm-chat"
diff --git a/commune/modules/model/chat_models/human.py b/commune/modules/model/chat_models/human.py
deleted file mode 100644
index 6c964c924..000000000
--- a/commune/modules/model/chat_models/human.py
+++ /dev/null
@@ -1,122 +0,0 @@
-"""ChatModel wrapper which returns user input as the response.."""
-import asyncio
-from functools import partial
-from io import StringIO
-from typing import Any, Callable, Dict, List, Mapping, Optional
-
-import yaml
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Field
-from langchain.schema.messages import (
- BaseMessage,
- HumanMessage,
- _message_from_dict,
- messages_to_dict,
-)
-from langchain.schema.output import ChatGeneration, ChatResult
-
-
-def _display_messages(messages: List[BaseMessage]) -> None:
- dict_messages = messages_to_dict(messages)
- for message in dict_messages:
- yaml_string = yaml.dump(
- message,
- default_flow_style=False,
- sort_keys=False,
- allow_unicode=True,
- width=10000,
- line_break=None,
- )
- print("\n", "======= start of message =======", "\n\n")
- print(yaml_string)
- print("======= end of message =======", "\n\n")
-
-
-def _collect_yaml_input(
- messages: List[BaseMessage], stop: Optional[List[str]] = None
-) -> BaseMessage:
- """Collects and returns user input as a single string."""
- lines = []
- while True:
- line = input()
- if not line.strip():
- break
- if stop and any(seq in line for seq in stop):
- break
- lines.append(line)
- yaml_string = "\n".join(lines)
-
- # Try to parse the input string as YAML
- try:
- message = _message_from_dict(yaml.safe_load(StringIO(yaml_string)))
- if message is None:
- return HumanMessage(content="")
- if stop:
- message.content = enforce_stop_tokens(message.content, stop)
- return message
- except yaml.YAMLError:
- raise ValueError("Invalid YAML string entered.")
- except ValueError:
- raise ValueError("Invalid message entered.")
-
-
-class HumanInputChatModel(BaseChatModel):
- """ChatModel which returns user input as the response."""
-
- input_func: Callable = Field(default_factory=lambda: _collect_yaml_input)
- message_func: Callable = Field(default_factory=lambda: _display_messages)
- separator: str = "\n"
- input_kwargs: Mapping[str, Any] = {}
- message_kwargs: Mapping[str, Any] = {}
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- return {
- "input_func": self.input_func.__name__,
- "message_func": self.message_func.__name__,
- }
-
- @property
- def _llm_type(self) -> str:
- """Returns the type of LLM."""
- return "human-input-chat-model"
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- """
- Displays the messages to the user and returns their input as a response.
-
- Args:
- messages (List[BaseMessage]): The messages to be displayed to the user.
- stop (Optional[List[str]]): A list of stop strings.
- run_manager (Optional[CallbackManagerForLLMRun]): Currently not used.
-
- Returns:
- ChatResult: The user's input as a response.
- """
- self.message_func(messages, **self.message_kwargs)
- user_input = self.input_func(messages, stop=stop, **self.input_kwargs)
- return ChatResult(generations=[ChatGeneration(message=user_input)])
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- func = partial(
- self._generate, messages, stop=stop, run_manager=run_manager, **kwargs
- )
- return await asyncio.get_event_loop().run_in_executor(None, func)
diff --git a/commune/modules/model/chat_models/jinachat.py b/commune/modules/model/chat_models/jinachat.py
deleted file mode 100644
index 7c1e6f903..000000000
--- a/commune/modules/model/chat_models/jinachat.py
+++ /dev/null
@@ -1,416 +0,0 @@
-"""JinaChat wrapper."""
-from __future__ import annotations
-
-import logging
-from typing import (
- Any,
- AsyncIterator,
- Callable,
- Dict,
- Iterator,
- List,
- Mapping,
- Optional,
- Tuple,
- Union,
-)
-
-from tenacity import (
- before_sleep_log,
- retry,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import (
- AIMessage,
- BaseMessage,
- ChatGeneration,
- ChatMessage,
- ChatResult,
- FunctionMessage,
- HumanMessage,
- SystemMessage,
-)
-from langchain.schema.messages import (
- AIMessageChunk,
- BaseMessageChunk,
- ChatMessageChunk,
- HumanMessageChunk,
- SystemMessageChunk,
-)
-from langchain.schema.output import ChatGenerationChunk
-from langchain.utils import get_from_dict_or_env, get_pydantic_field_names
-
-logger = logging.getLogger(__name__)
-
-
-def _create_retry_decorator(llm: JinaChat) -> Callable[[Any], Any]:
- import openai
-
- min_seconds = 1
- max_seconds = 60
- # Wait 2^x * 1 second between each retry starting with
- # 4 seconds, then up to 10 seconds, then 10 seconds afterwards
- return retry(
- reraise=True,
- stop=stop_after_attempt(llm.max_retries),
- wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
- retry=(
- retry_if_exception_type(openai.error.Timeout)
- | retry_if_exception_type(openai.error.APIError)
- | retry_if_exception_type(openai.error.APIConnectionError)
- | retry_if_exception_type(openai.error.RateLimitError)
- | retry_if_exception_type(openai.error.ServiceUnavailableError)
- ),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
-
-async def acompletion_with_retry(llm: JinaChat, **kwargs: Any) -> Any:
- """Use tenacity to retry the async completion call."""
- retry_decorator = _create_retry_decorator(llm)
-
- @retry_decorator
- async def _completion_with_retry(**kwargs: Any) -> Any:
- # Use OpenAI's async api https://github.com/openai/openai-python#async-api
- return await llm.client.acreate(**kwargs)
-
- return await _completion_with_retry(**kwargs)
-
-
-def _convert_delta_to_message_chunk(
- _dict: Mapping[str, Any], default_class: type[BaseMessageChunk]
-) -> BaseMessageChunk:
- role = _dict.get("role")
- content = _dict.get("content") or ""
-
- if role == "user" or default_class == HumanMessageChunk:
- return HumanMessageChunk(content=content)
- elif role == "assistant" or default_class == AIMessageChunk:
- return AIMessageChunk(content=content)
- elif role == "system" or default_class == SystemMessageChunk:
- return SystemMessageChunk(content=content)
- elif role or default_class == ChatMessageChunk:
- return ChatMessageChunk(content=content, role=role)
- else:
- return default_class(content=content)
-
-
-def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
- role = _dict["role"]
- if role == "user":
- return HumanMessage(content=_dict["content"])
- elif role == "assistant":
- content = _dict["content"] or ""
- return AIMessage(content=content)
- elif role == "system":
- return SystemMessage(content=_dict["content"])
- else:
- return ChatMessage(content=_dict["content"], role=role)
-
-
-def _convert_message_to_dict(message: BaseMessage) -> dict:
- if isinstance(message, ChatMessage):
- message_dict = {"role": message.role, "content": message.content}
- elif isinstance(message, HumanMessage):
- message_dict = {"role": "user", "content": message.content}
- elif isinstance(message, AIMessage):
- message_dict = {"role": "assistant", "content": message.content}
- elif isinstance(message, SystemMessage):
- message_dict = {"role": "system", "content": message.content}
- elif isinstance(message, FunctionMessage):
- message_dict = {
- "role": "function",
- "name": message.name,
- "content": message.content,
- }
- else:
- raise ValueError(f"Got unknown type {message}")
- if "name" in message.additional_kwargs:
- message_dict["name"] = message.additional_kwargs["name"]
- return message_dict
-
-
-class JinaChat(BaseChatModel):
- """`Jina AI` Chat models API.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``JINACHAT_API_KEY`` set to your API key, which you
- can generate at https://chat.jina.ai/api.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import JinaChat
- chat = JinaChat()
- """
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"jinachat_api_key": "JINACHAT_API_KEY"}
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- client: Any #: :meta private:
- temperature: float = 0.7
- """What sampling temperature to use."""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not explicitly specified."""
- jinachat_api_key: Optional[str] = None
- """Base URL path for API requests,
- leave blank if not using a proxy or service emulator."""
- request_timeout: Optional[Union[float, Tuple[float, float]]] = None
- """Timeout for requests to JinaChat completion API. Default is 600 seconds."""
- max_retries: int = 6
- """Maximum number of retries to make when generating."""
- streaming: bool = False
- """Whether to stream the results or not."""
- max_tokens: Optional[int] = None
- """Maximum number of tokens to generate."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- allow_population_by_field_name = True
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = get_pydantic_field_names(cls)
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- if field_name not in all_required_field_names:
- logger.warning(
- f"""WARNING! {field_name} is not default parameter.
- {field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
-
- invalid_model_kwargs = all_required_field_names.intersection(extra.keys())
- if invalid_model_kwargs:
- raise ValueError(
- f"Parameters {invalid_model_kwargs} should be specified explicitly. "
- f"Instead they were passed in as part of `model_kwargs` parameter."
- )
-
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["jinachat_api_key"] = get_from_dict_or_env(
- values, "jinachat_api_key", "JINACHAT_API_KEY"
- )
- try:
- import openai
-
- except ImportError:
- raise ValueError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`."
- )
- try:
- values["client"] = openai.ChatCompletion
- except AttributeError:
- raise ValueError(
- "`openai` has no `ChatCompletion` attribute, this is likely "
- "due to an old version of the openai package. Try upgrading it "
- "with `pip install --upgrade openai`."
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling JinaChat API."""
- return {
- "request_timeout": self.request_timeout,
- "max_tokens": self.max_tokens,
- "stream": self.streaming,
- "temperature": self.temperature,
- **self.model_kwargs,
- }
-
- def _create_retry_decorator(self) -> Callable[[Any], Any]:
- import openai
-
- min_seconds = 1
- max_seconds = 60
- # Wait 2^x * 1 second between each retry starting with
- # 4 seconds, then up to 10 seconds, then 10 seconds afterwards
- return retry(
- reraise=True,
- stop=stop_after_attempt(self.max_retries),
- wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
- retry=(
- retry_if_exception_type(openai.error.Timeout)
- | retry_if_exception_type(openai.error.APIError)
- | retry_if_exception_type(openai.error.APIConnectionError)
- | retry_if_exception_type(openai.error.RateLimitError)
- | retry_if_exception_type(openai.error.ServiceUnavailableError)
- ),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
- def completion_with_retry(self, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = self._create_retry_decorator()
-
- @retry_decorator
- def _completion_with_retry(**kwargs: Any) -> Any:
- return self.client.create(**kwargs)
-
- return _completion_with_retry(**kwargs)
-
- def _combine_llm_outputs(self, llm_outputs: List[Optional[dict]]) -> dict:
- overall_token_usage: dict = {}
- for output in llm_outputs:
- if output is None:
- # Happens in streaming
- continue
- token_usage = output["token_usage"]
- for k, v in token_usage.items():
- if k in overall_token_usage:
- overall_token_usage[k] += v
- else:
- overall_token_usage[k] = v
- return {"token_usage": overall_token_usage}
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs, "stream": True}
-
- default_chunk_class = AIMessageChunk
- for chunk in self.completion_with_retry(messages=message_dicts, **params):
- delta = chunk["choices"][0]["delta"]
- chunk = _convert_delta_to_message_chunk(delta, default_chunk_class)
- default_chunk_class = chunk.__class__
- yield ChatGenerationChunk(message=chunk)
- if run_manager:
- run_manager.on_llm_new_token(chunk.content)
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if self.streaming:
- generation: Optional[ChatGenerationChunk] = None
- for chunk in self._stream(
- messages=messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return ChatResult(generations=[generation])
-
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs}
- response = self.completion_with_retry(messages=message_dicts, **params)
- return self._create_chat_result(response)
-
- def _create_message_dicts(
- self, messages: List[BaseMessage], stop: Optional[List[str]]
- ) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]:
- params = dict(self._invocation_params)
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
- params["stop"] = stop
- message_dicts = [_convert_message_to_dict(m) for m in messages]
- return message_dicts, params
-
- def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
- generations = []
- for res in response["choices"]:
- message = _convert_dict_to_message(res["message"])
- gen = ChatGeneration(message=message)
- generations.append(gen)
- llm_output = {"token_usage": response["usage"]}
- return ChatResult(generations=generations, llm_output=llm_output)
-
- async def _astream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs, "stream": True}
-
- default_chunk_class = AIMessageChunk
- async for chunk in await acompletion_with_retry(
- self, messages=message_dicts, **params
- ):
- delta = chunk["choices"][0]["delta"]
- chunk = _convert_delta_to_message_chunk(delta, default_chunk_class)
- default_chunk_class = chunk.__class__
- yield ChatGenerationChunk(message=chunk)
- if run_manager:
- await run_manager.on_llm_new_token(chunk.content)
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if self.streaming:
- generation: Optional[ChatGenerationChunk] = None
- async for chunk in self._astream(
- messages=messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return ChatResult(generations=[generation])
-
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs}
- response = await acompletion_with_retry(self, messages=message_dicts, **params)
- return self._create_chat_result(response)
-
- @property
- def _invocation_params(self) -> Mapping[str, Any]:
- """Get the parameters used to invoke the model."""
- jinachat_creds: Dict[str, Any] = {
- "api_key": self.jinachat_api_key,
- "api_base": "https://api.chat.jina.ai/v1",
- "model": "jinachat",
- }
- return {**jinachat_creds, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of chat model."""
- return "jinachat"
diff --git a/commune/modules/model/chat_models/litellm.py b/commune/modules/model/chat_models/litellm.py
deleted file mode 100644
index f429c3221..000000000
--- a/commune/modules/model/chat_models/litellm.py
+++ /dev/null
@@ -1,461 +0,0 @@
-"""Wrapper around LiteLLM's model I/O library."""
-from __future__ import annotations
-
-import logging
-from typing import (
- Any,
- AsyncIterator,
- Callable,
- Dict,
- Iterator,
- List,
- Mapping,
- Optional,
- Tuple,
- Union,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.llms.base import create_base_retry_decorator
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import (
- ChatGeneration,
- ChatResult,
-)
-from langchain.schema.messages import (
- AIMessage,
- AIMessageChunk,
- BaseMessage,
- BaseMessageChunk,
- ChatMessage,
- ChatMessageChunk,
- HumanMessage,
- HumanMessageChunk,
- SystemMessage,
- SystemMessageChunk,
-)
-from langchain.schema.output import ChatGenerationChunk
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class ChatLiteLLMException(Exception):
- """Error with the `LiteLLM I/O` library"""
-
-
-def _truncate_at_stop_tokens(
- text: str,
- stop: Optional[List[str]],
-) -> str:
- """Truncates text at the earliest stop token found."""
- if stop is None:
- return text
-
- for stop_token in stop:
- stop_token_idx = text.find(stop_token)
- if stop_token_idx != -1:
- text = text[:stop_token_idx]
- return text
-
-
-class FunctionMessage(BaseMessage):
- """Message for passing the result of executing a function back to a model."""
-
- name: str
- """The name of the function that was executed."""
-
- @property
- def type(self) -> str:
- """Type of the message, used for serialization."""
- return "function"
-
-
-class FunctionMessageChunk(FunctionMessage, BaseMessageChunk):
- """Message Chunk for passing the result of executing a function back to a model."""
-
- pass
-
-
-def _create_retry_decorator(
- llm: ChatLiteLLM,
- run_manager: Optional[
- Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]
- ] = None,
-) -> Callable[[Any], Any]:
- """Returns a tenacity retry decorator, preconfigured to handle PaLM exceptions"""
- import openai
-
- errors = [
- openai.error.Timeout,
- openai.error.APIError,
- openai.error.APIConnectionError,
- openai.error.RateLimitError,
- openai.error.ServiceUnavailableError,
- ]
- return create_base_retry_decorator(
- error_types=errors, max_retries=llm.max_retries, run_manager=run_manager
- )
-
-
-def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
- role = _dict["role"]
- if role == "user":
- return HumanMessage(content=_dict["content"])
- elif role == "assistant":
- # Fix for azure
- # Also OpenAI returns None for tool invocations
- content = _dict.get("content", "") or ""
- if _dict.get("function_call"):
- additional_kwargs = {"function_call": dict(_dict["function_call"])}
- else:
- additional_kwargs = {}
- return AIMessage(content=content, additional_kwargs=additional_kwargs)
- elif role == "system":
- return SystemMessage(content=_dict["content"])
- elif role == "function":
- return FunctionMessage(content=_dict["content"], name=_dict["name"])
- else:
- return ChatMessage(content=_dict["content"], role=role)
-
-
-async def acompletion_with_retry(
- llm: ChatLiteLLM,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the async completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- async def _completion_with_retry(**kwargs: Any) -> Any:
- # Use OpenAI's async api https://github.com/openai/openai-python#async-api
- return await llm.client.acreate(**kwargs)
-
- return await _completion_with_retry(**kwargs)
-
-
-def _convert_delta_to_message_chunk(
- _dict: Mapping[str, Any], default_class: type[BaseMessageChunk]
-) -> BaseMessageChunk:
- role = _dict.get("role")
- content = _dict.get("content") or ""
- if _dict.get("function_call"):
- additional_kwargs = {"function_call": dict(_dict["function_call"])}
- else:
- additional_kwargs = {}
-
- if role == "user" or default_class == HumanMessageChunk:
- return HumanMessageChunk(content=content)
- elif role == "assistant" or default_class == AIMessageChunk:
- return AIMessageChunk(content=content, additional_kwargs=additional_kwargs)
- elif role == "system" or default_class == SystemMessageChunk:
- return SystemMessageChunk(content=content)
- elif role == "function" or default_class == FunctionMessageChunk:
- return FunctionMessageChunk(content=content, name=_dict["name"])
- elif role or default_class == ChatMessageChunk:
- return ChatMessageChunk(content=content, role=role)
- else:
- return default_class(content=content)
-
-
-def _convert_message_to_dict(message: BaseMessage) -> dict:
- if isinstance(message, ChatMessage):
- message_dict = {"role": message.role, "content": message.content}
- elif isinstance(message, HumanMessage):
- message_dict = {"role": "user", "content": message.content}
- elif isinstance(message, AIMessage):
- message_dict = {"role": "assistant", "content": message.content}
- if "function_call" in message.additional_kwargs:
- message_dict["function_call"] = message.additional_kwargs["function_call"]
- elif isinstance(message, SystemMessage):
- message_dict = {"role": "system", "content": message.content}
- elif isinstance(message, FunctionMessage):
- message_dict = {
- "role": "function",
- "content": message.content,
- "name": message.name,
- }
- else:
- raise ValueError(f"Got unknown type {message}")
- if "name" in message.additional_kwargs:
- message_dict["name"] = message.additional_kwargs["name"]
- return message_dict
-
-
-class ChatLiteLLM(BaseChatModel):
- """`LiteLLM` Chat models API.
-
- 1. The ``GOOGLE_API_KEY``` environment variable set with your API key, or
- 2. Pass your API key using the google_api_key kwarg to the ChatGoogle
- constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ChatGooglePalm
- chat = ChatGooglePalm()
-
- """
-
- client: Any #: :meta private:
- model: str = "gpt-3.5-turbo"
- model_name: Optional[str] = None
- """Model name to use."""
- openai_api_key: Optional[str] = None
- azure_api_key: Optional[str] = None
- anthropic_api_key: Optional[str] = None
- replicate_api_key: Optional[str] = None
- cohere_api_key: Optional[str] = None
- openrouter_api_key: Optional[str] = None
- streaming: bool = False
- api_base: Optional[str] = None
- organization: Optional[str] = None
- custom_llm_provider: Optional[str] = None
- request_timeout: Optional[Union[float, Tuple[float, float]]] = None
- temperature: Optional[float] = 1
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Run inference with this temperature. Must by in the closed
- interval [0.0, 1.0]."""
- top_p: Optional[float] = None
- """Decode using nucleus sampling: consider the smallest set of tokens whose
- probability sum is at least top_p. Must be in the closed interval [0.0, 1.0]."""
- top_k: Optional[int] = None
- """Decode using top-k sampling: consider the set of top_k most probable tokens.
- Must be positive."""
- n: int = 1
- """Number of chat completions to generate for each prompt. Note that the API may
- not return the full n completions if duplicates are generated."""
- max_tokens: int = 256
-
- max_retries: int = 6
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- set_model_value = self.model
- if self.model_name is not None:
- set_model_value = self.model_name
- return {
- "model": set_model_value,
- "force_timeout": self.request_timeout,
- "max_tokens": self.max_tokens,
- "stream": self.streaming,
- "n": self.n,
- "temperature": self.temperature,
- **self.model_kwargs,
- }
-
- @property
- def _client_params(self) -> Dict[str, Any]:
- """Get the parameters used for the openai client."""
- set_model_value = self.model
- if self.model_name is not None:
- set_model_value = self.model_name
- self.client.api_base = self.api_base
- self.client.organization = self.organization
- creds: Dict[str, Any] = {
- "model": set_model_value,
- "force_timeout": self.request_timeout,
- }
- return {**self._default_params, **creds}
-
- def completion_with_retry(
- self, run_manager: Optional[CallbackManagerForLLMRun] = None, **kwargs: Any
- ) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(self, run_manager=run_manager)
-
- @retry_decorator
- def _completion_with_retry(**kwargs: Any) -> Any:
- return self.client.completion(**kwargs)
-
- return _completion_with_retry(**kwargs)
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate api key, python package exists, temperature, top_p, and top_k."""
- try:
- import litellm
- except ImportError:
- raise ChatLiteLLMException(
- "Could not import google.generativeai python package. "
- "Please install it with `pip install google-generativeai`"
- )
-
- values["openai_api_key"] = get_from_dict_or_env(
- values, "openai_api_key", "OPENAI_API_KEY", default=""
- )
- values["azure_api_key"] = get_from_dict_or_env(
- values, "azure_api_key", "AZURE_API_KEY", default=""
- )
- values["anthropic_api_key"] = get_from_dict_or_env(
- values, "anthropic_api_key", "ANTHROPIC_API_KEY", default=""
- )
- values["replicate_api_key"] = get_from_dict_or_env(
- values, "replicate_api_key", "REPLICATE_API_KEY", default=""
- )
- values["openrouter_api_key"] = get_from_dict_or_env(
- values, "openrouter_api_key", "OPENROUTER_API_KEY", default=""
- )
- values["client"] = litellm
-
- if values["temperature"] is not None and not 0 <= values["temperature"] <= 1:
- raise ValueError("temperature must be in the range [0.0, 1.0]")
-
- if values["top_p"] is not None and not 0 <= values["top_p"] <= 1:
- raise ValueError("top_p must be in the range [0.0, 1.0]")
-
- if values["top_k"] is not None and values["top_k"] <= 0:
- raise ValueError("top_k must be positive")
-
- return values
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if stream if stream is not None else self.streaming:
- generation: Optional[ChatGenerationChunk] = None
- for chunk in self._stream(
- messages=messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return ChatResult(generations=[generation])
-
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs}
- response = self.completion_with_retry(
- messages=message_dicts, run_manager=run_manager, **params
- )
- return self._create_chat_result(response)
-
- def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
- generations = []
- for res in response["choices"]:
- message = _convert_dict_to_message(res["message"])
- gen = ChatGeneration(
- message=message,
- generation_info=dict(finish_reason=res.get("finish_reason")),
- )
- generations.append(gen)
- token_usage = response.get("usage", {})
- set_model_value = self.model
- if self.model_name is not None:
- set_model_value = self.model_name
- llm_output = {"token_usage": token_usage, "model": set_model_value}
- return ChatResult(generations=generations, llm_output=llm_output)
-
- def _create_message_dicts(
- self, messages: List[BaseMessage], stop: Optional[List[str]]
- ) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]:
- params = self._client_params
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
- params["stop"] = stop
- message_dicts = [_convert_message_to_dict(m) for m in messages]
- return message_dicts, params
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs, "stream": True}
-
- default_chunk_class = AIMessageChunk
- for chunk in self.completion_with_retry(
- messages=message_dicts, run_manager=run_manager, **params
- ):
- if len(chunk["choices"]) == 0:
- continue
- delta = chunk["choices"][0]["delta"]
- chunk = _convert_delta_to_message_chunk(delta, default_chunk_class)
- default_chunk_class = chunk.__class__
- yield ChatGenerationChunk(message=chunk)
- if run_manager:
- run_manager.on_llm_new_token(chunk.content)
-
- async def _astream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs, "stream": True}
-
- default_chunk_class = AIMessageChunk
- async for chunk in await acompletion_with_retry(
- self, messages=message_dicts, run_manager=run_manager, **params
- ):
- if len(chunk["choices"]) == 0:
- continue
- delta = chunk["choices"][0]["delta"]
- chunk = _convert_delta_to_message_chunk(delta, default_chunk_class)
- default_chunk_class = chunk.__class__
- yield ChatGenerationChunk(message=chunk)
- if run_manager:
- await run_manager.on_llm_new_token(chunk.content)
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if stream if stream is not None else self.streaming:
- generation: Optional[ChatGenerationChunk] = None
- async for chunk in self._astream(
- messages=messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return ChatResult(generations=[generation])
-
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs}
- response = await acompletion_with_retry(
- self, messages=message_dicts, run_manager=run_manager, **params
- )
- return self._create_chat_result(response)
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- set_model_value = self.model
- if self.model_name is not None:
- set_model_value = self.model_name
- return {
- "model": set_model_value,
- "temperature": self.temperature,
- "top_p": self.top_p,
- "top_k": self.top_k,
- "n": self.n,
- }
-
- @property
- def _llm_type(self) -> str:
- return "litellm-chat"
diff --git a/commune/modules/model/chat_models/mlflow_ai_gateway.py b/commune/modules/model/chat_models/mlflow_ai_gateway.py
deleted file mode 100644
index a1c02abb7..000000000
--- a/commune/modules/model/chat_models/mlflow_ai_gateway.py
+++ /dev/null
@@ -1,204 +0,0 @@
-import asyncio
-import logging
-from functools import partial
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.pydantic_v1 import BaseModel, Extra
-from langchain.schema import (
- ChatGeneration,
- ChatResult,
-)
-from langchain.schema.messages import (
- AIMessage,
- BaseMessage,
- ChatMessage,
- FunctionMessage,
- HumanMessage,
- SystemMessage,
-)
-
-logger = logging.getLogger(__name__)
-
-
-# Ignoring type because below is valid pydantic code
-# Unexpected keyword argument "extra" for "__init_subclass__" of "object" [call-arg]
-class ChatParams(BaseModel, extra=Extra.allow): # type: ignore[call-arg]
- """Parameters for the `MLflow AI Gateway` LLM."""
-
- temperature: float = 0.0
- candidate_count: int = 1
- """The number of candidates to return."""
- stop: Optional[List[str]] = None
- max_tokens: Optional[int] = None
-
-
-class ChatMLflowAIGateway(BaseChatModel):
- """`MLflow AI Gateway` chat models API.
-
- To use, you should have the ``mlflow[gateway]`` python package installed.
- For more information, see https://mlflow.org/docs/latest/gateway/index.html.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ChatMLflowAIGateway
-
- chat = ChatMLflowAIGateway(
- gateway_uri="",
- route="",
- params={
- "temperature": 0.1
- }
- )
- """
-
- def __init__(self, **kwargs: Any):
- try:
- import mlflow.gateway
- except ImportError as e:
- raise ImportError(
- "Could not import `mlflow.gateway` module. "
- "Please install it with `pip install mlflow[gateway]`."
- ) from e
-
- super().__init__(**kwargs)
- if self.gateway_uri:
- mlflow.gateway.set_gateway_uri(self.gateway_uri)
-
- route: str
- gateway_uri: Optional[str] = None
- params: Optional[ChatParams] = None
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- params: Dict[str, Any] = {
- "gateway_uri": self.gateway_uri,
- "route": self.route,
- **(self.params.dict() if self.params else {}),
- }
- return params
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- try:
- import mlflow.gateway
- except ImportError as e:
- raise ImportError(
- "Could not import `mlflow.gateway` module. "
- "Please install it with `pip install mlflow[gateway]`."
- ) from e
-
- message_dicts = [
- ChatMLflowAIGateway._convert_message_to_dict(message)
- for message in messages
- ]
- data: Dict[str, Any] = {
- "messages": message_dicts,
- **(self.params.dict() if self.params else {}),
- }
-
- resp = mlflow.gateway.query(self.route, data=data)
- return ChatMLflowAIGateway._create_chat_result(resp)
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- func = partial(
- self._generate, messages, stop=stop, run_manager=run_manager, **kwargs
- )
- return await asyncio.get_event_loop().run_in_executor(None, func)
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- return self._default_params
-
- def _get_invocation_params(
- self, stop: Optional[List[str]] = None, **kwargs: Any
- ) -> Dict[str, Any]:
- """Get the parameters used to invoke the model FOR THE CALLBACKS."""
- return {
- **self._default_params,
- **super()._get_invocation_params(stop=stop, **kwargs),
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of chat model."""
- return "mlflow-ai-gateway-chat"
-
- @staticmethod
- def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
- role = _dict["role"]
- content = _dict["content"]
- if role == "user":
- return HumanMessage(content=content)
- elif role == "assistant":
- return AIMessage(content=content)
- elif role == "system":
- return SystemMessage(content=content)
- else:
- return ChatMessage(content=content, role=role)
-
- @staticmethod
- def _raise_functions_not_supported() -> None:
- raise ValueError(
- "Function messages are not supported by the MLflow AI Gateway. Please"
- " create a feature request at https://github.com/mlflow/mlflow/issues."
- )
-
- @staticmethod
- def _convert_message_to_dict(message: BaseMessage) -> dict:
- if isinstance(message, ChatMessage):
- message_dict = {"role": message.role, "content": message.content}
- elif isinstance(message, HumanMessage):
- message_dict = {"role": "user", "content": message.content}
- elif isinstance(message, AIMessage):
- message_dict = {"role": "assistant", "content": message.content}
- elif isinstance(message, SystemMessage):
- message_dict = {"role": "system", "content": message.content}
- elif isinstance(message, FunctionMessage):
- raise ValueError(
- "Function messages are not supported by the MLflow AI Gateway. Please"
- " create a feature request at https://github.com/mlflow/mlflow/issues."
- )
- else:
- raise ValueError(f"Got unknown message type: {message}")
-
- if "function_call" in message.additional_kwargs:
- ChatMLflowAIGateway._raise_functions_not_supported()
- if message.additional_kwargs:
- logger.warning(
- "Additional message arguments are unsupported by MLflow AI Gateway "
- " and will be ignored: %s",
- message.additional_kwargs,
- )
- return message_dict
-
- @staticmethod
- def _create_chat_result(response: Mapping[str, Any]) -> ChatResult:
- generations = []
- for candidate in response["candidates"]:
- message = ChatMLflowAIGateway._convert_dict_to_message(candidate["message"])
- message_metadata = candidate.get("metadata", {})
- gen = ChatGeneration(
- message=message,
- generation_info=dict(message_metadata),
- )
- generations.append(gen)
-
- response_metadata = response.get("metadata", {})
- return ChatResult(generations=generations, llm_output=response_metadata)
diff --git a/commune/modules/model/chat_models/ollama.py b/commune/modules/model/chat_models/ollama.py
deleted file mode 100644
index a1fdcd0ac..000000000
--- a/commune/modules/model/chat_models/ollama.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import json
-from typing import Any, Iterator, List, Optional
-
-from langchain.callbacks.manager import (
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.llms.ollama import _OllamaCommon
-from langchain.schema import ChatResult
-from langchain.schema.messages import (
- AIMessage,
- AIMessageChunk,
- BaseMessage,
- ChatMessage,
- HumanMessage,
- SystemMessage,
-)
-from langchain.schema.output import ChatGeneration, ChatGenerationChunk
-
-
-def _stream_response_to_chat_generation_chunk(
- stream_response: str,
-) -> ChatGenerationChunk:
- """Convert a stream response to a generation chunk."""
- parsed_response = json.loads(stream_response)
- generation_info = parsed_response if parsed_response.get("done") is True else None
- return ChatGenerationChunk(
- message=AIMessageChunk(content=parsed_response.get("response", "")),
- generation_info=generation_info,
- )
-
-
-class ChatOllama(BaseChatModel, _OllamaCommon):
- """Ollama locally runs large language models.
-
- To use, follow the instructions at https://ollama.ai/.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ChatOllama
- ollama = ChatOllama(model="llama2")
- """
-
- @property
- def _llm_type(self) -> str:
- """Return type of chat model."""
- return "ollama-chat"
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- def _format_message_as_text(self, message: BaseMessage) -> str:
- if isinstance(message, ChatMessage):
- message_text = f"\n\n{message.role.capitalize()}: {message.content}"
- elif isinstance(message, HumanMessage):
- message_text = f"[INST] {message.content} [/INST]"
- elif isinstance(message, AIMessage):
- message_text = f"{message.content}"
- elif isinstance(message, SystemMessage):
- message_text = f"<> {message.content} <>"
- else:
- raise ValueError(f"Got unknown type {message}")
- return message_text
-
- def _format_messages_as_text(self, messages: List[BaseMessage]) -> str:
- return "\n".join(
- [self._format_message_as_text(message) for message in messages]
- )
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- """Call out to Ollama's generate endpoint.
-
- Args:
- messages: The list of base messages to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- Chat generations from the model
-
- Example:
- .. code-block:: python
-
- response = ollama([
- HumanMessage(content="Tell me about the history of AI")
- ])
- """
-
- prompt = self._format_messages_as_text(messages)
- final_chunk = super()._stream_with_aggregation(
- prompt, stop=stop, run_manager=run_manager, verbose=self.verbose, **kwargs
- )
- chat_generation = ChatGeneration(
- message=AIMessage(content=final_chunk.text),
- generation_info=final_chunk.generation_info,
- )
- return ChatResult(generations=[chat_generation])
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- prompt = self._format_messages_as_text(messages)
- for stream_resp in self._create_stream(prompt, stop, **kwargs):
- if stream_resp:
- chunk = _stream_response_to_chat_generation_chunk(stream_resp)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(
- chunk.text,
- verbose=self.verbose,
- )
diff --git a/commune/modules/model/chat_models/openai.py b/commune/modules/model/chat_models/openai.py
deleted file mode 100644
index 7cb1947cf..000000000
--- a/commune/modules/model/chat_models/openai.py
+++ /dev/null
@@ -1,532 +0,0 @@
-"""OpenAI chat wrapper."""
-from __future__ import annotations
-
-import logging
-import sys
-from typing import (
- TYPE_CHECKING,
- Any,
- AsyncIterator,
- Callable,
- Dict,
- Iterator,
- List,
- Mapping,
- Optional,
- Tuple,
- Union,
-)
-
-from langchain.adapters.openai import convert_dict_to_message, convert_message_to_dict
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models.base import BaseChatModel
-from langchain.llms.base import create_base_retry_decorator
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import ChatGeneration, ChatResult
-from langchain.schema.messages import (
- AIMessageChunk,
- BaseMessage,
- BaseMessageChunk,
- ChatMessageChunk,
- FunctionMessageChunk,
- HumanMessageChunk,
- SystemMessageChunk,
-)
-from langchain.schema.output import ChatGenerationChunk
-from langchain.utils import get_from_dict_or_env, get_pydantic_field_names
-
-if TYPE_CHECKING:
- import tiktoken
-
-logger = logging.getLogger(__name__)
-
-
-def _import_tiktoken() -> Any:
- try:
- import tiktoken
- except ImportError:
- raise ValueError(
- "Could not import tiktoken python package. "
- "This is needed in order to calculate get_token_ids. "
- "Please install it with `pip install tiktoken`."
- )
- return tiktoken
-
-
-def _create_retry_decorator(
- llm: ChatOpenAI,
- run_manager: Optional[
- Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]
- ] = None,
-) -> Callable[[Any], Any]:
- import openai
-
- errors = [
- openai.error.Timeout,
- openai.error.APIError,
- openai.error.APIConnectionError,
- openai.error.RateLimitError,
- openai.error.ServiceUnavailableError,
- ]
- return create_base_retry_decorator(
- error_types=errors, max_retries=llm.max_retries, run_manager=run_manager
- )
-
-
-async def acompletion_with_retry(
- llm: ChatOpenAI,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the async completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- async def _completion_with_retry(**kwargs: Any) -> Any:
- # Use OpenAI's async api https://github.com/openai/openai-python#async-api
- return await llm.client.acreate(**kwargs)
-
- return await _completion_with_retry(**kwargs)
-
-
-def _convert_delta_to_message_chunk(
- _dict: Mapping[str, Any], default_class: type[BaseMessageChunk]
-) -> BaseMessageChunk:
- role = _dict.get("role")
- content = _dict.get("content") or ""
- if _dict.get("function_call"):
- additional_kwargs = {"function_call": dict(_dict["function_call"])}
- else:
- additional_kwargs = {}
-
- if role == "user" or default_class == HumanMessageChunk:
- return HumanMessageChunk(content=content)
- elif role == "assistant" or default_class == AIMessageChunk:
- return AIMessageChunk(content=content, additional_kwargs=additional_kwargs)
- elif role == "system" or default_class == SystemMessageChunk:
- return SystemMessageChunk(content=content)
- elif role == "function" or default_class == FunctionMessageChunk:
- return FunctionMessageChunk(content=content, name=_dict["name"])
- elif role or default_class == ChatMessageChunk:
- return ChatMessageChunk(content=content, role=role)
- else:
- return default_class(content=content)
-
-
-class ChatOpenAI(BaseChatModel):
- """`OpenAI` Chat large language models API.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``OPENAI_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import ChatOpenAI
- openai = ChatOpenAI(model_name="gpt-3.5-turbo")
- """
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"openai_api_key": "OPENAI_API_KEY"}
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- client: Any = None #: :meta private:
- model_name: str = Field(default="gpt-3.5-turbo", alias="model")
- """Model name to use."""
- temperature: float = 0.7
- """What sampling temperature to use."""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not explicitly specified."""
- openai_api_key: Optional[str] = None
- """Base URL path for API requests,
- leave blank if not using a proxy or service emulator."""
- openai_api_base: Optional[str] = None
- openai_organization: Optional[str] = None
- # to support explicit proxy for OpenAI
- openai_proxy: Optional[str] = None
- request_timeout: Optional[Union[float, Tuple[float, float]]] = None
- """Timeout for requests to OpenAI completion API. Default is 600 seconds."""
- max_retries: int = 6
- """Maximum number of retries to make when generating."""
- streaming: bool = False
- """Whether to stream the results or not."""
- n: int = 1
- """Number of chat completions to generate for each prompt."""
- max_tokens: Optional[int] = None
- """Maximum number of tokens to generate."""
- tiktoken_model_name: Optional[str] = None
- """The model name to pass to tiktoken when using this class.
- Tiktoken is used to count the number of tokens in documents to constrain
- them to be under a certain limit. By default, when set to None, this will
- be the same as the embedding model name. However, there are some cases
- where you may want to use this Embedding class with a model name not
- supported by tiktoken. This can include when using Azure embeddings or
- when using one of the many model providers that expose an OpenAI-like
- API but with different models. In those cases, in order to avoid erroring
- when tiktoken is called, you can specify a model name to use here."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- allow_population_by_field_name = True
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = get_pydantic_field_names(cls)
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- if field_name not in all_required_field_names:
- logger.warning(
- f"""WARNING! {field_name} is not default parameter.
- {field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
-
- invalid_model_kwargs = all_required_field_names.intersection(extra.keys())
- if invalid_model_kwargs:
- raise ValueError(
- f"Parameters {invalid_model_kwargs} should be specified explicitly. "
- f"Instead they were passed in as part of `model_kwargs` parameter."
- )
-
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["openai_api_key"] = get_from_dict_or_env(
- values, "openai_api_key", "OPENAI_API_KEY"
- )
- values["openai_organization"] = get_from_dict_or_env(
- values,
- "openai_organization",
- "OPENAI_ORGANIZATION",
- default="",
- )
- values["openai_api_base"] = get_from_dict_or_env(
- values,
- "openai_api_base",
- "OPENAI_API_BASE",
- default="",
- )
- values["openai_proxy"] = get_from_dict_or_env(
- values,
- "openai_proxy",
- "OPENAI_PROXY",
- default="",
- )
- try:
- import openai
-
- except ImportError:
- raise ValueError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`."
- )
- try:
- values["client"] = openai.ChatCompletion
- except AttributeError:
- raise ValueError(
- "`openai` has no `ChatCompletion` attribute, this is likely "
- "due to an old version of the openai package. Try upgrading it "
- "with `pip install --upgrade openai`."
- )
- if values["n"] < 1:
- raise ValueError("n must be at least 1.")
- if values["n"] > 1 and values["streaming"]:
- raise ValueError("n must be 1 when streaming.")
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- return {
- "model": self.model_name,
- "request_timeout": self.request_timeout,
- "max_tokens": self.max_tokens,
- "stream": self.streaming,
- "n": self.n,
- "temperature": self.temperature,
- **self.model_kwargs,
- }
-
- def completion_with_retry(
- self, run_manager: Optional[CallbackManagerForLLMRun] = None, **kwargs: Any
- ) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(self, run_manager=run_manager)
-
- @retry_decorator
- def _completion_with_retry(**kwargs: Any) -> Any:
- return self.client.create(**kwargs)
-
- return _completion_with_retry(**kwargs)
-
- def _combine_llm_outputs(self, llm_outputs: List[Optional[dict]]) -> dict:
- overall_token_usage: dict = {}
- for output in llm_outputs:
- if output is None:
- # Happens in streaming
- continue
- token_usage = output["token_usage"]
- for k, v in token_usage.items():
- if k in overall_token_usage:
- overall_token_usage[k] += v
- else:
- overall_token_usage[k] = v
- return {"token_usage": overall_token_usage, "model_name": self.model_name}
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs, "stream": True}
-
- default_chunk_class = AIMessageChunk
- for chunk in self.completion_with_retry(
- messages=message_dicts, run_manager=run_manager, **params
- ):
- if len(chunk["choices"]) == 0:
- continue
- choice = chunk["choices"][0]
- chunk = _convert_delta_to_message_chunk(
- choice["delta"], default_chunk_class
- )
- finish_reason = choice.get("finish_reason")
- generation_info = (
- dict(finish_reason=finish_reason) if finish_reason is not None else None
- )
- default_chunk_class = chunk.__class__
- yield ChatGenerationChunk(message=chunk, generation_info=generation_info)
- if run_manager:
- run_manager.on_llm_new_token(chunk.content)
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if stream if stream is not None else self.streaming:
- generation: Optional[ChatGenerationChunk] = None
- for chunk in self._stream(
- messages=messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return ChatResult(generations=[generation])
-
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs}
- response = self.completion_with_retry(
- messages=message_dicts, run_manager=run_manager, **params
- )
- return self._create_chat_result(response)
-
- def _create_message_dicts(
- self, messages: List[BaseMessage], stop: Optional[List[str]]
- ) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]:
- params = self._client_params
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
- params["stop"] = stop
- message_dicts = [convert_message_to_dict(m) for m in messages]
- return message_dicts, params
-
- def _create_chat_result(self, response: Mapping[str, Any]) -> ChatResult:
- generations = []
- for res in response["choices"]:
- message = convert_dict_to_message(res["message"])
- gen = ChatGeneration(
- message=message,
- generation_info=dict(finish_reason=res.get("finish_reason")),
- )
- generations.append(gen)
- token_usage = response.get("usage", {})
- llm_output = {"token_usage": token_usage, "model_name": self.model_name}
- return ChatResult(generations=generations, llm_output=llm_output)
-
- async def _astream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[ChatGenerationChunk]:
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs, "stream": True}
-
- default_chunk_class = AIMessageChunk
- async for chunk in await acompletion_with_retry(
- self, messages=message_dicts, run_manager=run_manager, **params
- ):
- if len(chunk["choices"]) == 0:
- continue
- choice = chunk["choices"][0]
- chunk = _convert_delta_to_message_chunk(
- choice["delta"], default_chunk_class
- )
- finish_reason = choice.get("finish_reason")
- generation_info = (
- dict(finish_reason=finish_reason) if finish_reason is not None else None
- )
- default_chunk_class = chunk.__class__
- yield ChatGenerationChunk(message=chunk, generation_info=generation_info)
- if run_manager:
- await run_manager.on_llm_new_token(chunk.content)
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if stream if stream is not None else self.streaming:
- generation: Optional[ChatGenerationChunk] = None
- async for chunk in self._astream(
- messages=messages, stop=stop, run_manager=run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return ChatResult(generations=[generation])
-
- message_dicts, params = self._create_message_dicts(messages, stop)
- params = {**params, **kwargs}
- response = await acompletion_with_retry(
- self, messages=message_dicts, run_manager=run_manager, **params
- )
- return self._create_chat_result(response)
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_name": self.model_name}, **self._default_params}
-
- @property
- def _client_params(self) -> Dict[str, Any]:
- """Get the parameters used for the openai client."""
- openai_creds: Dict[str, Any] = {
- "api_key": self.openai_api_key,
- "api_base": self.openai_api_base,
- "organization": self.openai_organization,
- "model": self.model_name,
- }
- if self.openai_proxy:
- import openai
-
- openai.proxy = {"http": self.openai_proxy, "https": self.openai_proxy} # type: ignore[assignment] # noqa: E501
- return {**self._default_params, **openai_creds}
-
- def _get_invocation_params(
- self, stop: Optional[List[str]] = None, **kwargs: Any
- ) -> Dict[str, Any]:
- """Get the parameters used to invoke the model."""
- return {
- "model": self.model_name,
- **super()._get_invocation_params(stop=stop),
- **self._default_params,
- **kwargs,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of chat model."""
- return "openai-chat"
-
- def _get_encoding_model(self) -> Tuple[str, tiktoken.Encoding]:
- tiktoken_ = _import_tiktoken()
- if self.tiktoken_model_name is not None:
- model = self.tiktoken_model_name
- else:
- model = self.model_name
- if model == "gpt-3.5-turbo":
- # gpt-3.5-turbo may change over time.
- # Returning num tokens assuming gpt-3.5-turbo-0301.
- model = "gpt-3.5-turbo-0301"
- elif model == "gpt-4":
- # gpt-4 may change over time.
- # Returning num tokens assuming gpt-4-0314.
- model = "gpt-4-0314"
- # Returns the number of tokens used by a list of messages.
- try:
- encoding = tiktoken_.encoding_for_model(model)
- except KeyError:
- logger.warning("Warning: model not found. Using cl100k_base encoding.")
- model = "cl100k_base"
- encoding = tiktoken_.get_encoding(model)
- return model, encoding
-
- def get_token_ids(self, text: str) -> List[int]:
- """Get the tokens present in the text with tiktoken package."""
- # tiktoken NOT supported for Python 3.7 or below
- if sys.version_info[1] <= 7:
- return super().get_token_ids(text)
- _, encoding_model = self._get_encoding_model()
- return encoding_model.encode(text)
-
- def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int:
- """Calculate num tokens for gpt-3.5-turbo and gpt-4 with tiktoken package.
-
- Official documentation: https://github.com/openai/openai-cookbook/blob/
- main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb"""
- if sys.version_info[1] <= 7:
- return super().get_num_tokens_from_messages(messages)
- model, encoding = self._get_encoding_model()
- if model.startswith("gpt-3.5-turbo-0301"):
- # every message follows {role/name}\n{content}\n
- tokens_per_message = 4
- # if there's a name, the role is omitted
- tokens_per_name = -1
- elif model.startswith("gpt-3.5-turbo") or model.startswith("gpt-4"):
- tokens_per_message = 3
- tokens_per_name = 1
- else:
- raise NotImplementedError(
- f"get_num_tokens_from_messages() is not presently implemented "
- f"for model {model}."
- "See https://github.com/openai/openai-python/blob/main/chatml.md for "
- "information on how messages are converted to tokens."
- )
- num_tokens = 0
- messages_dict = [convert_message_to_dict(m) for m in messages]
- for message in messages_dict:
- num_tokens += tokens_per_message
- for key, value in message.items():
- # Cast str(value) in case the message value is not a string
- # This occurs with function messages
- num_tokens += len(encoding.encode(str(value)))
- if key == "name":
- num_tokens += tokens_per_name
- # every reply is primed with assistant
- num_tokens += 3
- return num_tokens
diff --git a/commune/modules/model/chat_models/promptlayer_openai.py b/commune/modules/model/chat_models/promptlayer_openai.py
deleted file mode 100644
index 2f29b548e..000000000
--- a/commune/modules/model/chat_models/promptlayer_openai.py
+++ /dev/null
@@ -1,135 +0,0 @@
-"""PromptLayer wrapper."""
-import datetime
-from typing import Any, Dict, List, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.chat_models import ChatOpenAI
-from langchain.schema import ChatResult
-from langchain.schema.messages import BaseMessage
-
-
-class PromptLayerChatOpenAI(ChatOpenAI):
- """`PromptLayer` and `OpenAI` Chat large language models API.
-
- To use, you should have the ``openai`` and ``promptlayer`` python
- package installed, and the environment variable ``OPENAI_API_KEY``
- and ``PROMPTLAYER_API_KEY`` set with your openAI API key and
- promptlayer key respectively.
-
- All parameters that can be passed to the OpenAI LLM can also
- be passed here. The PromptLayerChatOpenAI adds to optional
-
- parameters:
- ``pl_tags``: List of strings to tag the request with.
- ``return_pl_id``: If True, the PromptLayer request ID will be
- returned in the ``generation_info`` field of the
- ``Generation`` object.
-
- Example:
- .. code-block:: python
-
- from langchain.chat_models import PromptLayerChatOpenAI
- openai = PromptLayerChatOpenAI(model_name="gpt-3.5-turbo")
- """
-
- pl_tags: Optional[List[str]]
- return_pl_id: Optional[bool] = False
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any
- ) -> ChatResult:
- """Call ChatOpenAI generate and then call PromptLayer API to log the request."""
- from promptlayer.utils import get_api_key, promptlayer_api_request
-
- request_start_time = datetime.datetime.now().timestamp()
- generated_responses = super()._generate(
- messages, stop, run_manager, stream=stream, **kwargs
- )
- request_end_time = datetime.datetime.now().timestamp()
- message_dicts, params = super()._create_message_dicts(messages, stop)
- for i, generation in enumerate(generated_responses.generations):
- response_dict, params = super()._create_message_dicts(
- [generation.message], stop
- )
- params = {**params, **kwargs}
- pl_request_id = promptlayer_api_request(
- "langchain.PromptLayerChatOpenAI",
- "langchain",
- message_dicts,
- params,
- self.pl_tags,
- response_dict,
- request_start_time,
- request_end_time,
- get_api_key(),
- return_pl_id=self.return_pl_id,
- )
- if self.return_pl_id:
- if generation.generation_info is None or not isinstance(
- generation.generation_info, dict
- ):
- generation.generation_info = {}
- generation.generation_info["pl_request_id"] = pl_request_id
- return generated_responses
-
- async def _agenerate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any
- ) -> ChatResult:
- """Call ChatOpenAI agenerate and then call PromptLayer to log."""
- from promptlayer.utils import get_api_key, promptlayer_api_request_async
-
- request_start_time = datetime.datetime.now().timestamp()
- generated_responses = await super()._agenerate(
- messages, stop, run_manager, stream=stream, **kwargs
- )
- request_end_time = datetime.datetime.now().timestamp()
- message_dicts, params = super()._create_message_dicts(messages, stop)
- for i, generation in enumerate(generated_responses.generations):
- response_dict, params = super()._create_message_dicts(
- [generation.message], stop
- )
- params = {**params, **kwargs}
- pl_request_id = await promptlayer_api_request_async(
- "langchain.PromptLayerChatOpenAI.async",
- "langchain",
- message_dicts,
- params,
- self.pl_tags,
- response_dict,
- request_start_time,
- request_end_time,
- get_api_key(),
- return_pl_id=self.return_pl_id,
- )
- if self.return_pl_id:
- if generation.generation_info is None or not isinstance(
- generation.generation_info, dict
- ):
- generation.generation_info = {}
- generation.generation_info["pl_request_id"] = pl_request_id
- return generated_responses
-
- @property
- def _llm_type(self) -> str:
- return "promptlayer-openai-chat"
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- return {
- **super()._identifying_params,
- "pl_tags": self.pl_tags,
- "return_pl_id": self.return_pl_id,
- }
diff --git a/commune/modules/model/chat_models/vertexai.py b/commune/modules/model/chat_models/vertexai.py
deleted file mode 100644
index 79a80b6b4..000000000
--- a/commune/modules/model/chat_models/vertexai.py
+++ /dev/null
@@ -1,160 +0,0 @@
-"""Wrapper around Google VertexAI chat-based models."""
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Dict, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.chat_models.base import BaseChatModel
-from langchain.llms.vertexai import _VertexAICommon, is_codey_model
-from langchain.pydantic_v1 import root_validator
-from langchain.schema import (
- ChatGeneration,
- ChatResult,
-)
-from langchain.schema.messages import (
- AIMessage,
- BaseMessage,
- HumanMessage,
- SystemMessage,
-)
-from langchain.utilities.vertexai import raise_vertex_import_error
-
-if TYPE_CHECKING:
- from vertexai.language_models import ChatMessage, InputOutputTextPair
-
-
-@dataclass
-class _ChatHistory:
- """Represents a context and a history of messages."""
-
- history: List["ChatMessage"] = field(default_factory=list)
- context: Optional[str] = None
-
-
-def _parse_chat_history(history: List[BaseMessage]) -> _ChatHistory:
- """Parse a sequence of messages into history.
-
- Args:
- history: The list of messages to re-create the history of the chat.
- Returns:
- A parsed chat history.
- Raises:
- ValueError: If a sequence of message has a SystemMessage not at the
- first place.
- """
- from vertexai.language_models import ChatMessage
-
- vertex_messages, context = [], None
- for i, message in enumerate(history):
- if i == 0 and isinstance(message, SystemMessage):
- context = message.content
- elif isinstance(message, AIMessage):
- vertex_message = ChatMessage(content=message.content, author="bot")
- vertex_messages.append(vertex_message)
- elif isinstance(message, HumanMessage):
- vertex_message = ChatMessage(content=message.content, author="user")
- vertex_messages.append(vertex_message)
- else:
- raise ValueError(
- f"Unexpected message with type {type(message)} at the position {i}."
- )
- chat_history = _ChatHistory(context=context, history=vertex_messages)
- return chat_history
-
-
-def _parse_examples(examples: List[BaseMessage]) -> List["InputOutputTextPair"]:
- from vertexai.language_models import InputOutputTextPair
-
- if len(examples) % 2 != 0:
- raise ValueError(
- f"Expect examples to have an even amount of messages, got {len(examples)}."
- )
- example_pairs = []
- input_text = None
- for i, example in enumerate(examples):
- if i % 2 == 0:
- if not isinstance(example, HumanMessage):
- raise ValueError(
- f"Expected the first message in a part to be from human, got "
- f"{type(example)} for the {i}th message."
- )
- input_text = example.content
- if i % 2 == 1:
- if not isinstance(example, AIMessage):
- raise ValueError(
- f"Expected the second message in a part to be from AI, got "
- f"{type(example)} for the {i}th message."
- )
- pair = InputOutputTextPair(
- input_text=input_text, output_text=example.content
- )
- example_pairs.append(pair)
- return example_pairs
-
-
-class ChatVertexAI(_VertexAICommon, BaseChatModel):
- """`Vertex AI` Chat large language models API."""
-
- model_name: str = "chat-bison"
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that the python package exists in environment."""
- cls._try_init_vertexai(values)
- try:
- if is_codey_model(values["model_name"]):
- from vertexai.preview.language_models import CodeChatModel
-
- values["client"] = CodeChatModel.from_pretrained(values["model_name"])
- else:
- from vertexai.preview.language_models import ChatModel
-
- values["client"] = ChatModel.from_pretrained(values["model_name"])
- except ImportError:
- raise_vertex_import_error(minimum_expected_version="1.29.0")
- return values
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- """Generate next turn in the conversation.
-
- Args:
- messages: The history of the conversation as a list of messages. Code chat
- does not support context.
- stop: The list of stop words (optional).
- run_manager: The CallbackManager for LLM run, it's not used at the moment.
-
- Returns:
- The ChatResult that contains outputs generated by the model.
-
- Raises:
- ValueError: if the last message in the list is not from human.
- """
- if not messages:
- raise ValueError(
- "You should provide at least one message to start the chat!"
- )
- question = messages[-1]
- if not isinstance(question, HumanMessage):
- raise ValueError(
- f"Last message in the list should be from human, got {question.type}."
- )
- history = _parse_chat_history(messages[:-1])
- context = history.context if history.context else None
- params = {**self._default_params, **kwargs}
- examples = kwargs.get("examples", None)
- if examples:
- params["examples"] = _parse_examples(examples)
- if not self.is_codey_model:
- chat = self.client.start_chat(
- context=context, message_history=history.history, **params
- )
- else:
- chat = self.client.start_chat(message_history=history.history, **params)
- response = chat.send_message(question.content)
- text = self._enforce_stop_words(response.text, stop)
- return ChatResult(generations=[ChatGeneration(message=AIMessage(content=text))])
diff --git a/commune/modules/model/diffusion/diffusion.py b/commune/modules/model/diffusion/diffusion.py
deleted file mode 100644
index ae3963ae1..000000000
--- a/commune/modules/model/diffusion/diffusion.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import commune as c
-from diffusers import DiffusionPipeline
-import torch
-class DiffisionPipeline(c.Module):
- def __init__(self, config=None, **kwargs):
- config = self.set_config(config=config, kwargs=kwargs)
- self.set_model(config.model)
-
- def set_model(self, model:str):
- c.ensure_lib("diffusers")
- from diffusers import DiffusionPipeline
- import torch
-
- # load both base & refiner
- self.base = DiffusionPipeline.from_pretrained(model, torch_dtype=torch.float16, variant=self.config.variant, use_safetensors=True
- )
- self.base.to(self.config.device)
-
- def generate(self,
- prompt: str = "A majestic lion jumping from a big stone at night",
- n_steps: int =40,
- high_noise_frac: float = 0.8,
- output_type: str ="image"):
- """
- Generate an image from a prompt using the diffusion model.
- """
-
-
- # run both experts
- images = self.base(
- prompt=prompt,
- num_inference_steps=n_steps,
- denoising_end=high_noise_frac,
- output_type=output_type,
- ).images
-
-
- return images
-
-
- @classmethod
- def test(cls, **kwargs):
- self = cls(**kwargs)
- return self.generate()
\ No newline at end of file
diff --git a/commune/modules/model/diffusion/diffusion.yaml b/commune/modules/model/diffusion/diffusion.yaml
deleted file mode 100644
index 1eb8a8fd7..000000000
--- a/commune/modules/model/diffusion/diffusion.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-model: stabilityai/stable-diffusion-xl-base-1.0
-variant: fp16
-device: cuda
\ No newline at end of file
diff --git a/commune/modules/model/diffusion/stable_diffusion.py b/commune/modules/model/diffusion/stable_diffusion.py
deleted file mode 100644
index 93eab9216..000000000
--- a/commune/modules/model/diffusion/stable_diffusion.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler
-import commune
-from typing import *
-
-
-class StableDiffusion:
- def __init__(self, model_name:str="stabilityai/stable-diffusion-2", device:str = "cuda"):
- self.model_name = model_name
- # Use the Euler scheduler here instead
- self.scheduler = EulerDiscreteScheduler.from_pretrained(model_name, subfolder="scheduler")
- self.pipe = StableDiffusionPipeline.from_pretrained(model_name, scheduler=self.scheduler, torch_dtype=torch.float16)
- self.pipe = self.pipe.to(device)
-
- @property
- def device(self) -> str:
- return self.pipe.device
-
- def generate(self,
- prompt:str = "a photo of an astronaut riding a horse on mars",
- **kwargs):
- image = pipe(prompt, **kwargs).images[0]
- return image
- @classmethod
- def test(cls):
- self = cls()
- self = self.generate()
- print(output)
-
-if __name__ == "__main__":
- StableDiffusion.run()
-
\ No newline at end of file
diff --git a/commune/modules/model/hf/model_hf.py b/commune/modules/model/hf/model_hf.py
deleted file mode 100644
index 4b1469eac..000000000
--- a/commune/modules/model/hf/model_hf.py
+++ /dev/null
@@ -1,548 +0,0 @@
-from pprint import pp
-import asyncio
-from copy import deepcopy
-from typing import Union, Optional, List
-import os, sys
-from typing import *
-from loguru import logger
-import torch
-from torch import nn
-import commune as c
-
-# we are inheriting from the base model class which is a c.Module and a torch.nn.Module
-Model = c.module('model')
-
-class ModelTransformer(Model):
- default_config = c.config('model.hf')
- shortcuts = default_config.shortcuts
- def __init__(self,
- config = None,
- **kwargs
- ):
- config = self.set_config(config=config, kwargs=kwargs)
- Model.init_model(self)
- self.set_model(config)
-
-
- def forward(self,
- input_ids: Union[str, torch.Tensor],
- attention_mask: torch.Tensor = None,
- return_keys:List[str] = ['topk', 'hidden_states'],
- topk:int=32,
- hidden_layer: int = -1, # -1 is the last hidden layer
- max_input_tokens : int = 256,
- **kwargs):
-
-
- if isinstance(input_ids, str) or isinstance(input_ids, list):
- input_ids = self.tokenize(input_ids)['input_ids']
- elif isinstance(input_ids, torch.Tensor):
- input_ids = input_ids
-
- # resolve the max sequence length (sometimes we want to clip the input to make it faster)
- attention_mask = attention_mask if isinstance(attention_mask, torch.Tensor) else torch.ones_like(input_ids)
-
- if max_input_tokens > self.config.max_input_tokens:
- max_input_tokens = self.config.max_input_tokens
- logger.warning(f"max_input_tokens is larger than the model's max_input_tokens. Clipping to {max_input_tokens}")
-
- sample = {
- 'input_ids': input_ids[:, -max_input_tokens:],
- 'attention_mask': attention_mask[:, -max_input_tokens:] if attention_mask is not None else None
- }
-
- # move to device for all tensors
- for k,v in sample.items():
- if isinstance(v, torch.Tensor):
- sample[k] = sample[k].to(self.device)
-
-
- # clip the input ids to the vocab size to avoid index errors
- sample['input_ids'] = torch.clip(sample['input_ids'], 0, self.tokenizer.vocab_size-1)
-
- output_hidden_states = 'hidden_states' in return_keys
- output_topk = 'topk' in return_keys
-
- # forward pass
- output = self.model(input_ids=sample['input_ids'].to(self.device),
- output_hidden_states=output_hidden_states, **kwargs)
-
-
- if output_hidden_states:
- output['hidden_states'] = output.hidden_states[hidden_layer].detach()
-
- if output_topk:
- output['topk']=self.encode_topk(output['logits'].detach(), topk=topk)
- return {key:output[key] for key in return_keys}
-
-
- def encode(self, text:str, token_idx:int = None, **kwargs) -> torch.Tensor:
- kwargs['return_keys'] = ['hidden_states']
- sample = self.tokenize(text)
- kwargs.update(sample)
- hidden_states = self.forward(**kwargs)['hidden_states']
- if isinstance(token_idx, int):
- return hidden_states[:,token_idx, :]
- else:
- return hidden_states
-
- embed = encode
-
- def resolve_quantize(self, config):
- if config.quantize == None:
- for q in ['int4', 'int8']:
- if q in config.model:
- config.quantize = q
- if config.quantize != None:
- c.ensure_lib('bitsandbytes')
- c.ensure_lib('scipy')
-
- if config.quantize == 'int4':
- config['load_in_4bit'] = True
- if config.quantize == 'int8':
- config['load_in_8bit'] = True
-
- return config
-
- def set_model(self, config) -> None:
- config.model = config.shortcuts.get(config.model, config.model)
- from transformers import AutoModelForCausalLM
-
-
-
- config = self.resolve_quantize(config)
-
- config.device_map = c.infer_device_map(config.model, quantize=config.quantize)
-
-
- kwargs = {
- 'device_map': config.device_map,
- 'max_memory': config.max_memory,
- 'trust_remote_code': config.trust_remote_code,
- 'offload_folder': "offload",
- 'torch_dtype': torch.float16,
- 'load_in_4bit': config.load_in_4bit,
- 'load_in_8bit': config.load_in_8bit,
-
- }
-
-
- t = c.time()
-
- c.print(f'LAUNCH PARAMS for {config.model} -> ',kwargs)
- c.print(config.model)
- self.model = AutoModelForCausalLM.from_pretrained(config.model,**kwargs)
-
- self.devices = config.devices = list(set(list(self.model.hf_device_map.values())))
- self.device = config.device = self.devices[0]
- time_taken = c.time() - t
- c.print(f'MODEL LOADED ({time_taken}s) on {self.devices}', config.model)
- if not config.quantize: # cant finetune with quantization
- self.set_finetune(config.finetune)
- self.set_optimizer(config.optimizer)
-
- c.print('FINETUNE SET -> ', config.finetune)
- if config.load:
- self.load(keys=['model', 'optimizer'])
-
-
- c.print('SETTING Tokenizer -> ', config.model)
- self.set_tokenizer(config.model)
- c.print('Tokenizer SET -> ', config.model)
-
-
- def set_tokenizer(self, tokenizer:str):
- from transformers import AutoTokenizer
- try:
- tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast=True)
- except ValueError:
-
- print('resorting ot use_fast = False')
- tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast=False)
-
-
- if not hasattr(tokenizer, 'pad_token') or tokenizer.pad_token is None:
- assert hasattr(tokenizer, 'eos_token') and tokenizer.eos_token is not None
- tokenizer.add_special_tokens({'pad_token': tokenizer.eos_token})
-
- self.tokenizer = tokenizer
-
- return self.tokenizer
-
-
-
- @staticmethod
- def encode_topk( forward_response_tensor: torch.Tensor , topk:int=4096) -> torch.Tensor:
- """ Returns topk tokens/probabilities given unnormalized logits as input. """
-
- #import ipdb; ipdb.set_trace()
-
- logits = forward_response_tensor # unnormalized logit scores: [batch_size, sequence_len, vocab_size]
- probs = torch.softmax(logits, dim=-1).to(torch.float32) # normalized probabilities: [batch_size, sequence_len, vocab_size]
-
- topk_indices = torch.argsort(probs, dim=-1, descending=True)[...,:topk]
- # topk_values, topk_indices = torch.topk(probs, topk) # topk probs and indices: [batch_size, sequence_len, topk]
-
- topk_values = probs.gather( index=topk_indices, dim=-1)
- encoded_probs = torch.cat([topk_values, topk_indices], dim=-1) # [batch_size, sequence_len, topk + topk]
- return encoded_probs # [batch_size, sequence_len, topk + topk]
-
-
- @staticmethod
- def decode_topk( forward_response_tensor: torch.Tensor, topk=4096, vocab_size:int=50257) -> torch.Tensor:
- """ Returns full logits by decoding topk-encoding input. """
- batch_size, sequence_len, _ = forward_response_tensor.shape
-
- encoded_probs = forward_response_tensor # encoded probabilities: [batch_size, sequence_len, topk + topk]
- topk_values = encoded_probs[..., :topk] # topk probs: [batch_size, sequence_len, topk]
- topk_indices = encoded_probs[..., topk:].long() # topk probs indices: [batch_size, sequence_len, topk]
-
- topk_pmass = topk_values.sum(dim=-1) # topk probability mass: [batch_size, sequence_len]
- remainder_pmass = torch.clamp(1 - topk_pmass, 1e-40, 1) # remainder probability mass: [batch_size, sequence_len]
- remainder_floor = remainder_pmass / (vocab_size - topk) # divide remainder: [batch_size, sequence_len]
-
- logits = torch.ones((batch_size, sequence_len, vocab_size), dtype=topk_values.dtype).to(topk_values.device)
- logits *= torch.log(remainder_floor)[:, :, None] # set probability floor: [batch_size, sequence_len, vocab_size]
-
- logits.scatter_(-1, topk_indices, torch.log(topk_values + 1e-40)) # insert topk probs: [batch_size, sequence_len, vocab_size]
-
- return logits # [batch_size, sequence_len, vocab_size]
-
-
- def tokenizer_name(self):
- return self.config['tokenizer']
-
- def tokenize(self,
- text: str = 'Whadup',
- padding=True,
- truncation=True,
- max_length=64,
- return_tensors='pt',
- add_special_tokens=False,
- device:str = None,
- **kwargs) -> torch.Tensor:
- """ Returns tokenized text as torch tensor. """
-
- sample = self.tokenizer(text, padding=padding,
- truncation=truncation,
- max_length=max_length,
- return_tensors=return_tensors,
- add_special_tokens=add_special_tokens,
- **kwargs) # assume tokenizer.padding_side = 'left'
-
- device = device if device != None else self.device
-
- sample = dict(
- input_ids= sample['input_ids'].to(device),
- attention_mask= sample['attention_mask'].to(device)
- )
-
- return sample
-
-
-
- def detokenize(self, input_ids: torch.Tensor, **kwargs) -> torch.Tensor:
- """ Returns tokenized text as torch tensor. """
-
- text = self.tokenizer.batch_decode(input_ids,**kwargs) # assume tokenizer.padding_side = 'left'
-
- return text
-
-
- @classmethod
- def sample_check(cls, sample):
- return bool(isinstance(sample, dict) and 'input_ids' in sample)
-
- @classmethod
- async def async_get_sample(cls, dataset, max_trials=10, batch_size=1, sequence_length=64, num_batches=10):
- sample = None
- if not hasattr(cls, 'dataset_pool'):
- cls.dataset_pool = c.connect_pool(dataset)
-
- fail_count = 0
-
- while not cls.sample_check(sample) and fail_count < max_trials:
- if len(cls.dataset_pool) == 0:
- cls.dataset_pool = c.connect_pool(dataset)
- try:
- data_idx =cls.choice(list(range(len(cls.dataset_pool))))
- sample = cls.dataset_pool[data_idx].sample(batch_size=batch_size,
- sequence_length=sequence_length)
-
- if not cls.sample_check(sample):
- raise Exception('Sample check failed')
- sample['input_ids'] = sample['input_ids'][:batch_size, -sequence_length:]
-
-
- except Exception as e:
- fail_count += 1
- del cls.dataset_pool[data_idx]
- cls.print(f'ERROR {e} failed to sample, removing dataset {data_idx}, {len(cls.dataset_pool)} remaining', color='red')
- assert cls.sample_check(sample), f'Failed to sample from {dataset} after {max_trials} trials.'
- return sample
-
- @classmethod
- def get_sample(cls, timeout=2, retries = 3, *args, **kwargs):
- try:
- if timeout:
- # Add timeout to the async_get_sample call
- coro = asyncio.wait_for(cls.async_get_sample(*args, **kwargs), timeout=timeout)
- else:
- coro = cls.async_get_sample(*args, **kwargs)
-
- return asyncio.run(coro)
- except asyncio.TimeoutError:
- # Handle the timeout error here
- print("Async function call timed out.")
- if retries > 0:
- return cls.get_sample(timeout=timeout, retries=retries-1, *args, **kwargs)
-
-
-
- @classmethod
- def resolve_model(cls, model, **kwargs):
- if isinstance(model, str):
- if cls.exists(model):
- model = cls.connect(model)
- else:
- model = cls(model=model, **kwargs)
- elif isinstance(model, nn.Module):
- model = model
- elif isinstance(model, dict):
- model = cls(**model)
- elif model == None:
- model = cls()
- else:
- raise ValueError(f"Model type {type(model)} not supported.")
-
-
- return model
-
-
- @property
- def tag(self):
- if self.config.get('tag', None) == None:
- self.config['tag'] = 'base'
-
- return self.config['tag']
-
- @tag.setter
- def tag(self, tag):
- self.config['tag'] = tag
-
-
- def test(self):
- c.print(self.generate('whatup'))
-
- @classmethod
- def test_encode(cls, text=['encode, hey whadup fam how is it going']*4, num_samples:int=10):
- self = cls()
- t = cls.timer()
- for i in range(num_samples):
- cls.print(self.encode(text).shape)
- cls.print(num_samples/t.seconds, 'samples per second')
-
-
- @classmethod
- def resolve_server_name(cls, tag=None, **kwargs):
- config = cls.get_config(kwargs=kwargs)
- server_name = 'model.'+config.model
- if tag != None :
- server_name += '::' + str(tag)
- return server_name
-
- @classmethod
- def serve_fleet(cls,
- *args,
- tags=None,
- n = 2,
- **kwargs
- ):
- if tags == None:
- tag = ''
-
- for i in range(n):
- cls.serve(*args, tag=tag+str(i), **kwargs)
-
-
- @classmethod
- def serve(cls,
- model: str,
- tag = None,
- refresh = True,
- server_name = None,
- **kwargs
- ):
-
- config = cls.get_config(kwargs=kwargs)
- config.tag = tag
- config.model = model
- config.pop('shortcuts', None)
- kwargs.update(
- {
- 'tag': tag,
- 'config': config,
- 'refresh': refresh,
- 'verbose': True,
- 'module': cls.module_path(),
- 'server_name': cls.resolve_server_name(**config) if server_name == None else server_name
- }
- )
-
- return c.serve(**kwargs)
-
- @classmethod
- def calculate_loss( cls, logits: torch.Tensor,
- input_ids:torch.Tensor,
- return_value = False,
- **kwargs) -> torch.Tensor:
- '''
- Calculate the loss for the model.
- '''
- gt = input_ids[:, -(logits.shape[1]-1):].flatten()
- pred = logits[:, :-1]
-
- if len(pred.shape) == 3:
- pred = pred.reshape(-1, pred.shape[-1])
-
- assert gt.shape[0] == pred.shape[0], f'gt.shape: {gt.shape} pred.shape: {pred.shape}'
-
- loss_fn = torch.nn.CrossEntropyLoss()
- loss = loss_fn(pred, gt.to(pred.device))
-
- # check if loss is nan
- if torch.isnan(loss):
- c.print('Loss is nan, skipping backward pass')
- train = False
- loss = torch.tensor(10)
- raise Exception('Loss is nan, skipping backward pass')
-
- if return_value:
- loss = loss.item()
-
- return loss
-
-
- def generate_stream(self, text: str,
- max_length: int = 20,
- max_new_tokens: int = None,
- min_length: int = 0,
- min_new_tokens: int = None,
- early_stopping: bool = True,
- max_time: float = None,
- chunk_size: int = 10,
- **kwargs) -> List[str]:
- if isinstance(text, str):
- text = [text]
-
-
- input_ids = self.tokenize(text)['input_ids']
- for i in range(max_new_tokens):
- output_ids = self.model.generate(input_ids,
- max_length=max_length,
- max_new_tokens=chunk_size,
- min_length=min_length,
- min_new_tokens=min_new_tokens,
- early_stopping=early_stopping,
- max_time=max_time, **kwargs)
- output_text = self.decode(output_ids)
- yield output_text
- text = output_text
-
- hf = c.module('hf')()
- def generate(self, text: str,
- max_output_tokens: int = 256,
- max_input_tokens: int = 20,
- early_stopping: bool = True,
- stream:bool = False,
- **kwargs) -> List[str]:
- if stream:
- return self.generate_stream(text,
- max_new_tokens=max_output_tokens,
- early_stopping=early_stopping, **kwargs)
-
- is_string = isinstance(text, str)
- if is_string:
- text = [text]
-
- # resolve max_input_tokens
- if max_input_tokens > self.config.max_input_tokens:
- max_input_tokens = self.config.max_input_tokens
-
- # resolve max_output_tokens
- if max_output_tokens > self.config.max_output_tokens:
- max_output_tokens = self.config.max_output_tokens
-
- # get tokens
- input_ids = self.tokenize(text, max_length=max_input_tokens)['input_ids']
-
- # generate
- output_ids = self.model.generate(input_ids,
- max_new_tokens=max_output_tokens,
- early_stopping=early_stopping,
- **kwargs)
-
- # decode
- output_text = self.detokenize(output_ids, skip_special_tokens=True)
-
- # remove input text
- for t, ot in zip(text, output_text):
- output_text = ot.replace(t, '')
-
- if is_string and isinstance(output_text, list):
- output_text = output_text[0]
-
- return output_text
-
-
-
- @classmethod
- def test_generate(cls,model='gpt2.7b', text='Whadup?', **kwargs):
- model = cls(model=model, **kwargs)
- output_text = model.generate(text=text, max_output_tokens=100, early_stopping=False)
-
- return output_text
-
- @classmethod
- def test_encode(cls, model='gpt2.7b', text='Whadup?', **kwargs):
- from transformers import (
- AutoTokenizer,
- AutoModelForCausalLM,
- pipeline,
- )
- import torch
-
-
- name = "meta-llama/Llama-2-7b"
-
- tokenizer = AutoTokenizer.from_pretrained(name)
- tokenizer.pad_token_id = tokenizer.eos_token_id # for open-ended generation
-
- model = AutoModelForCausalLM.from_pretrained(
- name,
- quantization_config=bnb_config,
- device_map="auto",
- trust_remote_code=True,
- )
- generation_pipe = pipeline(
- "text-generation",
- model=model,
- tokenizer=tokenizer,
- trust_remote_code=True,
- device_map="auto", # finds GPU
- )
-
- text = "any text " # prompt goes here
-
- sequences = generation_pipe(
- text,
- max_length=128,
- pad_token_id=tokenizer.pad_token_id,
- eos_token_id=tokenizer.eos_token_id,
- do_sample=True,
- top_k=10,
- temperature=0.4,
- top_p=0.9
- )
-
- print(sequences[0]["generated_text"])
\ No newline at end of file
diff --git a/commune/modules/model/hf/model_hf.yaml b/commune/modules/model/hf/model_hf.yaml
deleted file mode 100644
index 71abb4e88..000000000
--- a/commune/modules/model/hf/model_hf.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-model: llama2.7b
-tag: base
-device: null
-device_map: null
-max_memory: null
-trust_remote_code: True
-finetune: 1
-optimizer:
- lr: 2.0e-05
- module: torch.optim.Adam
-max_input_tokens: 256
-max_output_tokens: 256
-load_in_4bit: False
-load_in_8bit: False
-tag: null
-load: false
-quantize: null
-
-shortcuts:
- # 0-1B models
- gpt125m: 'EleutherAI/gpt-neo-125m'
- gpt2.7b: 'EleutherAI/gpt-neo-2.7B'
- gpt3b: 'EleutherAI/gpt-neo-2.7B'
- opt1.3b: 'facebook/opt-1.3b'
- oa.pythia.12b: OpenAssistant/oasst-sft-1-pythia-12b
-
- vicuna.33b : lmsys/vicuna-33b-v1.3
- vicuna.13b: lmsys/vicuna-13b-v1.3
- vicuna.7b: lmsys/vicuna-7b-v1.3
-
- llama: openlm-research/open_llama_7b
-
- llama2.70b: meta-llama/Llama-2-70b-chat-hf
- llama2.7b: meta-llama/Llama-2-7b
-
- llama13b: openlm-research/open_llama_13b
- llama-trl: trl-lib/llama-7b-se-rl-peft
-
- pygmalion-6b: Pygmalionreplit/replit-code-v1-3bAI/pygmalion-6b
- stablellm7b: StabilityAI/stablelm-tuned-alpha-7b
- mosaic: mosaicml/mpt-30b
- falcon_40b_instruct: tiiuae/falcon-40b-instruct
- falcon_uncensored: ehartford/WizardLM-Uncensored-Falcon-40b
- falcon: tiiuae/falcon-40b-instruct
-
- open_llama_13b: openlm-research/open_llama_13b
- lazarus30b: CalderaAI/30B-Lazarus
- # code
- starcoder: bigcode/starcoder
- wizardcoder: WizardLM/WizardCoder-15B-V1.0
- replit_code: replit/replit-code-v1-3b
- bpt: robertmyers/bpt-instruct-rm-6b
- llamaint4: edumunozsala/llama-2-7b-int4-python-code-20k
- codegeex2: THUDM/codegeex2-6b-int4
- targon-7b: robertmyers/targon-7b
-
-block_prefix: model.layers
-model2block_prefix:
- mosaic: transformer.blocks
\ No newline at end of file
diff --git a/commune/modules/model/hf/textgen/clients/python/tests/conftest.py b/commune/modules/model/hf/textgen/clients/python/tests/conftest.py
deleted file mode 100644
index 48734f0da..000000000
--- a/commune/modules/model/hf/textgen/clients/python/tests/conftest.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import pytest
-
-from text_generation import __version__
-from huggingface_hub.utils import build_hf_headers
-
-
-@pytest.fixture
-def flan_t5_xxl():
- return "google/flan-t5-xxl"
-
-
-@pytest.fixture
-def fake_model():
- return "fake/model"
-
-
-@pytest.fixture
-def unsupported_model():
- return "gpt2"
-
-
-@pytest.fixture
-def base_url():
- return "https://api-inference.huggingface.co/models"
-
-
-@pytest.fixture
-def bloom_url(base_url, bloom_model):
- return f"{base_url}/{bloom_model}"
-
-
-@pytest.fixture
-def flan_t5_xxl_url(base_url, flan_t5_xxl):
- return f"{base_url}/{flan_t5_xxl}"
-
-
-@pytest.fixture
-def fake_url(base_url, fake_model):
- return f"{base_url}/{fake_model}"
-
-
-@pytest.fixture
-def unsupported_url(base_url, unsupported_model):
- return f"{base_url}/{unsupported_model}"
-
-
-@pytest.fixture(scope="session")
-def hf_headers():
- return build_hf_headers(
- library_name="text-generation-tests", library_version=__version__
- )
diff --git a/commune/modules/model/llm/ai21.py b/commune/modules/model/llm/ai21.py
deleted file mode 100644
index dc079c201..000000000
--- a/commune/modules/model/llm/ai21.py
+++ /dev/null
@@ -1,156 +0,0 @@
-from typing import Any, Dict, List, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import BaseModel, Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class AI21PenaltyData(BaseModel):
- """Parameters for AI21 penalty data."""
-
- scale: int = 0
- applyToWhitespaces: bool = True
- applyToPunctuations: bool = True
- applyToNumbers: bool = True
- applyToStopwords: bool = True
- applyToEmojis: bool = True
-
-
-class AI21(LLM):
- """AI21 large language models.
-
- To use, you should have the environment variable ``AI21_API_KEY``
- set with your API key.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import AI21
- ai21 = AI21(model="j2-jumbo-instruct")
- """
-
- model: str = "j2-jumbo-instruct"
- """Model name to use."""
-
- temperature: float = 0.7
- """What sampling temperature to use."""
-
- maxTokens: int = 256
- """The maximum number of tokens to generate in the completion."""
-
- minTokens: int = 0
- """The minimum number of tokens to generate in the completion."""
-
- topP: float = 1.0
- """Total probability mass of tokens to consider at each step."""
-
- presencePenalty: AI21PenaltyData = AI21PenaltyData()
- """Penalizes repeated tokens."""
-
- countPenalty: AI21PenaltyData = AI21PenaltyData()
- """Penalizes repeated tokens according to count."""
-
- frequencyPenalty: AI21PenaltyData = AI21PenaltyData()
- """Penalizes repeated tokens according to frequency."""
-
- numResults: int = 1
- """How many completions to generate for each prompt."""
-
- logitBias: Optional[Dict[str, float]] = None
- """Adjust the probability of specific tokens being generated."""
-
- ai21_api_key: Optional[str] = None
-
- stop: Optional[List[str]] = None
-
- base_url: Optional[str] = None
- """Base url to use, if None decides based on model name."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key exists in environment."""
- ai21_api_key = get_from_dict_or_env(values, "ai21_api_key", "AI21_API_KEY")
- values["ai21_api_key"] = ai21_api_key
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling AI21 API."""
- return {
- "temperature": self.temperature,
- "maxTokens": self.maxTokens,
- "minTokens": self.minTokens,
- "topP": self.topP,
- "presencePenalty": self.presencePenalty.dict(),
- "countPenalty": self.countPenalty.dict(),
- "frequencyPenalty": self.frequencyPenalty.dict(),
- "numResults": self.numResults,
- "logitBias": self.logitBias,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model": self.model}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "ai21"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to AI21's complete endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = ai21("Tell me a joke.")
- """
- if self.stop is not None and stop is not None:
- raise ValueError("`stop` found in both the input and default params.")
- elif self.stop is not None:
- stop = self.stop
- elif stop is None:
- stop = []
- if self.base_url is not None:
- base_url = self.base_url
- else:
- if self.model in ("j1-grande-instruct",):
- base_url = "https://api.ai21.com/studio/v1/experimental"
- else:
- base_url = "https://api.ai21.com/studio/v1"
- params = {**self._default_params, **kwargs}
- response = requests.post(
- url=f"{base_url}/{self.model}/complete",
- headers={"Authorization": f"Bearer {self.ai21_api_key}"},
- json={"prompt": prompt, "stopSequences": stop, **params},
- )
- if response.status_code != 200:
- optional_detail = response.json().get("error")
- raise ValueError(
- f"AI21 /complete call failed with status code {response.status_code}."
- f" Details: {optional_detail}"
- )
- response_json = response.json()
- return response_json["completions"][0]["data"]["text"]
diff --git a/commune/modules/model/llm/aleph_alpha.py b/commune/modules/model/llm/aleph_alpha.py
deleted file mode 100644
index 00235e776..000000000
--- a/commune/modules/model/llm/aleph_alpha.py
+++ /dev/null
@@ -1,286 +0,0 @@
-from typing import Any, Dict, List, Optional, Sequence
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class AlephAlpha(LLM):
- """Aleph Alpha large language models.
-
- To use, you should have the ``aleph_alpha_client`` python package installed, and the
- environment variable ``ALEPH_ALPHA_API_KEY`` set with your API key, or pass
- it as a named parameter to the constructor.
-
- Parameters are explained more in depth here:
- https://github.com/Aleph-Alpha/aleph-alpha-client/blob/c14b7dd2b4325c7da0d6a119f6e76385800e097b/aleph_alpha_client/completion.py#L10
-
- Example:
- .. code-block:: python
-
- from langchain.llms import AlephAlpha
- aleph_alpha = AlephAlpha(aleph_alpha_api_key="my-api-key")
- """
-
- client: Any #: :meta private:
- model: Optional[str] = "luminous-base"
- """Model name to use."""
-
- maximum_tokens: int = 64
- """The maximum number of tokens to be generated."""
-
- temperature: float = 0.0
- """A non-negative float that tunes the degree of randomness in generation."""
-
- top_k: int = 0
- """Number of most likely tokens to consider at each step."""
-
- top_p: float = 0.0
- """Total probability mass of tokens to consider at each step."""
-
- presence_penalty: float = 0.0
- """Penalizes repeated tokens."""
-
- frequency_penalty: float = 0.0
- """Penalizes repeated tokens according to frequency."""
-
- repetition_penalties_include_prompt: Optional[bool] = False
- """Flag deciding whether presence penalty or frequency penalty are
- updated from the prompt."""
-
- use_multiplicative_presence_penalty: Optional[bool] = False
- """Flag deciding whether presence penalty is applied
- multiplicatively (True) or additively (False)."""
-
- penalty_bias: Optional[str] = None
- """Penalty bias for the completion."""
-
- penalty_exceptions: Optional[List[str]] = None
- """List of strings that may be generated without penalty,
- regardless of other penalty settings"""
-
- penalty_exceptions_include_stop_sequences: Optional[bool] = None
- """Should stop_sequences be included in penalty_exceptions."""
-
- best_of: Optional[int] = None
- """returns the one with the "best of" results
- (highest log probability per token)
- """
-
- n: int = 1
- """How many completions to generate for each prompt."""
-
- logit_bias: Optional[Dict[int, float]] = None
- """The logit bias allows to influence the likelihood of generating tokens."""
-
- log_probs: Optional[int] = None
- """Number of top log probabilities to be returned for each generated token."""
-
- tokens: Optional[bool] = False
- """return tokens of completion."""
-
- disable_optimizations: Optional[bool] = False
-
- minimum_tokens: Optional[int] = 0
- """Generate at least this number of tokens."""
-
- echo: bool = False
- """Echo the prompt in the completion."""
-
- use_multiplicative_frequency_penalty: bool = False
-
- sequence_penalty: float = 0.0
-
- sequence_penalty_min_length: int = 2
-
- use_multiplicative_sequence_penalty: bool = False
-
- completion_bias_inclusion: Optional[Sequence[str]] = None
-
- completion_bias_inclusion_first_token_only: bool = False
-
- completion_bias_exclusion: Optional[Sequence[str]] = None
-
- completion_bias_exclusion_first_token_only: bool = False
- """Only consider the first token for the completion_bias_exclusion."""
-
- contextual_control_threshold: Optional[float] = None
- """If set to None, attention control parameters only apply to those tokens that have
- explicitly been set in the request.
- If set to a non-None value, control parameters are also applied to similar tokens.
- """
-
- control_log_additive: Optional[bool] = True
- """True: apply control by adding the log(control_factor) to attention scores.
- False: (attention_scores - - attention_scores.min(-1)) * control_factor
- """
-
- repetition_penalties_include_completion: bool = True
- """Flag deciding whether presence penalty or frequency penalty
- are updated from the completion."""
-
- raw_completion: bool = False
- """Force the raw completion of the model to be returned."""
-
- stop_sequences: Optional[List[str]] = None
- """Stop sequences to use."""
-
- # Client params
- aleph_alpha_api_key: Optional[str] = None
- """API key for Aleph Alpha API."""
- host: str = "https://api.aleph-alpha.com"
- """The hostname of the API host.
- The default one is "https://api.aleph-alpha.com")"""
- hosting: Optional[str] = None
- """Determines in which datacenters the request may be processed.
- You can either set the parameter to "aleph-alpha" or omit it (defaulting to None).
- Not setting this value, or setting it to None, gives us maximal
- flexibility in processing your request in our
- own datacenters and on servers hosted with other providers.
- Choose this option for maximal availability.
- Setting it to "aleph-alpha" allows us to only process the
- request in our own datacenters.
- Choose this option for maximal data privacy."""
- request_timeout_seconds: int = 305
- """Client timeout that will be set for HTTP requests in the
- `requests` library's API calls.
- Server will close all requests after 300 seconds with an internal server error."""
- total_retries: int = 8
- """The number of retries made in case requests fail with certain retryable
- status codes. If the last
- retry fails a corresponding exception is raised. Note, that between retries
- an exponential backoff
- is applied, starting with 0.5 s after the first retry and doubling for
- each retry made. So with the
- default setting of 8 retries a total wait time of 63.5 s is added
- between the retries."""
- nice: bool = False
- """Setting this to True, will signal to the API that you intend to be
- nice to other users
- by de-prioritizing your request below concurrent ones."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- aleph_alpha_api_key = get_from_dict_or_env(
- values, "aleph_alpha_api_key", "ALEPH_ALPHA_API_KEY"
- )
- try:
- from aleph_alpha_client import Client
-
- values["client"] = Client(
- token=aleph_alpha_api_key,
- host=values["host"],
- hosting=values["hosting"],
- request_timeout_seconds=values["request_timeout_seconds"],
- total_retries=values["total_retries"],
- nice=values["nice"],
- )
- except ImportError:
- raise ImportError(
- "Could not import aleph_alpha_client python package. "
- "Please install it with `pip install aleph_alpha_client`."
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling the Aleph Alpha API."""
- return {
- "maximum_tokens": self.maximum_tokens,
- "temperature": self.temperature,
- "top_k": self.top_k,
- "top_p": self.top_p,
- "presence_penalty": self.presence_penalty,
- "frequency_penalty": self.frequency_penalty,
- "n": self.n,
- "repetition_penalties_include_prompt": self.repetition_penalties_include_prompt, # noqa: E501
- "use_multiplicative_presence_penalty": self.use_multiplicative_presence_penalty, # noqa: E501
- "penalty_bias": self.penalty_bias,
- "penalty_exceptions": self.penalty_exceptions,
- "penalty_exceptions_include_stop_sequences": self.penalty_exceptions_include_stop_sequences, # noqa: E501
- "best_of": self.best_of,
- "logit_bias": self.logit_bias,
- "log_probs": self.log_probs,
- "tokens": self.tokens,
- "disable_optimizations": self.disable_optimizations,
- "minimum_tokens": self.minimum_tokens,
- "echo": self.echo,
- "use_multiplicative_frequency_penalty": self.use_multiplicative_frequency_penalty, # noqa: E501
- "sequence_penalty": self.sequence_penalty,
- "sequence_penalty_min_length": self.sequence_penalty_min_length,
- "use_multiplicative_sequence_penalty": self.use_multiplicative_sequence_penalty, # noqa: E501
- "completion_bias_inclusion": self.completion_bias_inclusion,
- "completion_bias_inclusion_first_token_only": self.completion_bias_inclusion_first_token_only, # noqa: E501
- "completion_bias_exclusion": self.completion_bias_exclusion,
- "completion_bias_exclusion_first_token_only": self.completion_bias_exclusion_first_token_only, # noqa: E501
- "contextual_control_threshold": self.contextual_control_threshold,
- "control_log_additive": self.control_log_additive,
- "repetition_penalties_include_completion": self.repetition_penalties_include_completion, # noqa: E501
- "raw_completion": self.raw_completion,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model": self.model}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "aleph_alpha"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Aleph Alpha's completion endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = aleph_alpha("Tell me a joke.")
- """
- from aleph_alpha_client import CompletionRequest, Prompt
-
- params = self._default_params
- if self.stop_sequences is not None and stop is not None:
- raise ValueError(
- "stop sequences found in both the input and default params."
- )
- elif self.stop_sequences is not None:
- params["stop_sequences"] = self.stop_sequences
- else:
- params["stop_sequences"] = stop
- params = {**params, **kwargs}
- request = CompletionRequest(prompt=Prompt.from_text(prompt), **params)
- response = self.client.complete(model=self.model, request=request)
- text = response.completions[0].completion
- # If stop tokens are provided, Aleph Alpha's endpoint returns them.
- # In order to make this consistent with other endpoints, we strip them.
- if stop is not None or self.stop_sequences is not None:
- text = enforce_stop_tokens(text, params["stop_sequences"])
- return text
-
-
-if __name__ == "__main__":
- aa = AlephAlpha()
-
- print(aa("How are you?"))
diff --git a/commune/modules/model/llm/amazon_api_gateway.py b/commune/modules/model/llm/amazon_api_gateway.py
deleted file mode 100644
index 3161c0bc2..000000000
--- a/commune/modules/model/llm/amazon_api_gateway.py
+++ /dev/null
@@ -1,104 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra
-
-
-class ContentHandlerAmazonAPIGateway:
- """Adapter to prepare the inputs from Langchain to a format
- that LLM model expects.
-
- It also provides helper function to extract
- the generated text from the model response."""
-
- @classmethod
- def transform_input(
- cls, prompt: str, model_kwargs: Dict[str, Any]
- ) -> Dict[str, Any]:
- return {"inputs": prompt, "parameters": model_kwargs}
-
- @classmethod
- def transform_output(cls, response: Any) -> str:
- return response.json()[0]["generated_text"]
-
-
-class AmazonAPIGateway(LLM):
- """Amazon API Gateway to access LLM models hosted on AWS."""
-
- api_url: str
- """API Gateway URL"""
-
- headers: Optional[Dict] = None
- """API Gateway HTTP Headers to send, e.g. for authentication"""
-
- model_kwargs: Optional[Dict] = None
- """Key word arguments to pass to the model."""
-
- content_handler: ContentHandlerAmazonAPIGateway = ContentHandlerAmazonAPIGateway()
- """The content handler class that provides an input and
- output transform functions to handle formats between LLM
- and the endpoint.
- """
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"api_url": self.api_url, "headers": self.headers},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "amazon_api_gateway"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Amazon API Gateway model.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = se("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
- payload = self.content_handler.transform_input(prompt, _model_kwargs)
-
- try:
- response = requests.post(
- self.api_url,
- headers=self.headers,
- json=payload,
- )
- text = self.content_handler.transform_output(response)
-
- except Exception as error:
- raise ValueError(f"Error raised by the service: {error}")
-
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
-
- return text
diff --git a/commune/modules/model/llm/anthropic.py b/commune/modules/model/llm/anthropic.py
deleted file mode 100644
index c75074d64..000000000
--- a/commune/modules/model/llm/anthropic.py
+++ /dev/null
@@ -1,341 +0,0 @@
-import re
-import warnings
-from typing import Any, AsyncIterator, Callable, Dict, Iterator, List, Mapping, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field, SecretStr, root_validator
-from langchain.schema.language_model import BaseLanguageModel
-from langchain.schema.output import GenerationChunk
-from langchain.schema.prompt import PromptValue
-from langchain.utils import (
- check_package_version,
- get_from_dict_or_env,
- get_pydantic_field_names,
-)
-from langchain.utils.utils import build_extra_kwargs
-
-
-class _AnthropicCommon(BaseLanguageModel):
- client: Any = None #: :meta private:
- async_client: Any = None #: :meta private:
- model: str = Field(default="claude-2", alias="model_name")
- """Model name to use."""
-
- max_tokens_to_sample: int = Field(default=256, alias="max_tokens")
- """Denotes the number of tokens to predict per generation."""
-
- temperature: Optional[float] = None
- """A non-negative float that tunes the degree of randomness in generation."""
-
- top_k: Optional[int] = None
- """Number of most likely tokens to consider at each step."""
-
- top_p: Optional[float] = None
- """Total probability mass of tokens to consider at each step."""
-
- streaming: bool = False
- """Whether to stream the results."""
-
- default_request_timeout: Optional[float] = None
- """Timeout for requests to Anthropic Completion API. Default is 600 seconds."""
-
- anthropic_api_url: Optional[str] = None
-
- anthropic_api_key: Optional[SecretStr] = None
-
- HUMAN_PROMPT: Optional[str] = None
- AI_PROMPT: Optional[str] = None
- count_tokens: Optional[Callable[[str], int]] = None
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict) -> Dict:
- extra = values.get("model_kwargs", {})
- all_required_field_names = get_pydantic_field_names(cls)
- values["model_kwargs"] = build_extra_kwargs(
- extra, values, all_required_field_names
- )
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["anthropic_api_key"] = SecretStr(
- get_from_dict_or_env(values, "anthropic_api_key", "ANTHROPIC_API_KEY")
- )
- # Get custom api url from environment.
- values["anthropic_api_url"] = get_from_dict_or_env(
- values,
- "anthropic_api_url",
- "ANTHROPIC_API_URL",
- default="https://api.anthropic.com",
- )
-
- try:
- import anthropic
-
- check_package_version("anthropic", gte_version="0.3")
- values["client"] = anthropic.Anthropic(
- base_url=values["anthropic_api_url"],
- api_key=values["anthropic_api_key"].get_secret_value(),
- timeout=values["default_request_timeout"],
- )
- values["async_client"] = anthropic.AsyncAnthropic(
- base_url=values["anthropic_api_url"],
- api_key=values["anthropic_api_key"].get_secret_value(),
- timeout=values["default_request_timeout"],
- )
- values["HUMAN_PROMPT"] = anthropic.HUMAN_PROMPT
- values["AI_PROMPT"] = anthropic.AI_PROMPT
- values["count_tokens"] = values["client"].count_tokens
-
- except ImportError:
- raise ImportError(
- "Could not import anthropic python package. "
- "Please it install it with `pip install anthropic`."
- )
- return values
-
- @property
- def _default_params(self) -> Mapping[str, Any]:
- """Get the default parameters for calling Anthropic API."""
- d = {
- "max_tokens_to_sample": self.max_tokens_to_sample,
- "model": self.model,
- }
- if self.temperature is not None:
- d["temperature"] = self.temperature
- if self.top_k is not None:
- d["top_k"] = self.top_k
- if self.top_p is not None:
- d["top_p"] = self.top_p
- return {**d, **self.model_kwargs}
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{}, **self._default_params}
-
- def _get_anthropic_stop(self, stop: Optional[List[str]] = None) -> List[str]:
- if not self.HUMAN_PROMPT or not self.AI_PROMPT:
- raise NameError("Please ensure the anthropic package is loaded")
-
- if stop is None:
- stop = []
-
- # Never want model to invent new turns of Human / Assistant dialog.
- stop.extend([self.HUMAN_PROMPT])
-
- return stop
-
-
-class Anthropic(LLM, _AnthropicCommon):
- """Anthropic large language models.
-
- To use, you should have the ``anthropic`` python package installed, and the
- environment variable ``ANTHROPIC_API_KEY`` set with your API key, or pass
- it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- import anthropic
- from langchain.llms import Anthropic
-
- model = Anthropic(model="", anthropic_api_key="my-api-key")
-
- # Simplest invocation, automatically wrapped with HUMAN_PROMPT
- # and AI_PROMPT.
- response = model("What are the biggest risks facing humanity?")
-
- # Or if you want to use the chat mode, build a few-shot-prompt, or
- # put words in the Assistant's mouth, use HUMAN_PROMPT and AI_PROMPT:
- raw_prompt = "What are the biggest risks facing humanity?"
- prompt = f"{anthropic.HUMAN_PROMPT} {prompt}{anthropic.AI_PROMPT}"
- response = model(prompt)
- """
-
- class Config:
- """Configuration for this pydantic object."""
-
- allow_population_by_field_name = True
- arbitrary_types_allowed = True
-
- @root_validator()
- def raise_warning(cls, values: Dict) -> Dict:
- """Raise warning that this class is deprecated."""
- warnings.warn(
- "This Anthropic LLM is deprecated. "
- "Please use `from langchain.chat_models import ChatAnthropic` instead"
- )
- return values
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "anthropic-llm"
-
- def _wrap_prompt(self, prompt: str) -> str:
- if not self.HUMAN_PROMPT or not self.AI_PROMPT:
- raise NameError("Please ensure the anthropic package is loaded")
-
- if prompt.startswith(self.HUMAN_PROMPT):
- return prompt # Already wrapped.
-
- # Guard against common errors in specifying wrong number of newlines.
- corrected_prompt, n_subs = re.subn(r"^\n*Human:", self.HUMAN_PROMPT, prompt)
- if n_subs == 1:
- return corrected_prompt
-
- # As a last resort, wrap the prompt ourselves to emulate instruct-style.
- return f"{self.HUMAN_PROMPT} {prompt}{self.AI_PROMPT} Sure, here you go:\n"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- r"""Call out to Anthropic's completion endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- prompt = "What are the biggest risks facing humanity?"
- prompt = f"\n\nHuman: {prompt}\n\nAssistant:"
- response = model(prompt)
-
- """
- if self.streaming:
- completion = ""
- for chunk in self._stream(
- prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- completion += chunk.text
- return completion
-
- stop = self._get_anthropic_stop(stop)
- params = {**self._default_params, **kwargs}
- response = self.client.completions.create(
- prompt=self._wrap_prompt(prompt),
- stop_sequences=stop,
- **params,
- )
- return response.completion
-
- def convert_prompt(self, prompt: PromptValue) -> str:
- return self._wrap_prompt(prompt.to_string())
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Anthropic's completion endpoint asynchronously."""
- if self.streaming:
- completion = ""
- async for chunk in self._astream(
- prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- completion += chunk.text
- return completion
-
- stop = self._get_anthropic_stop(stop)
- params = {**self._default_params, **kwargs}
-
- response = await self.async_client.completions.create(
- prompt=self._wrap_prompt(prompt),
- stop_sequences=stop,
- **params,
- )
- return response.completion
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- r"""Call Anthropic completion_stream and return the resulting generator.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- A generator representing the stream of tokens from Anthropic.
- Example:
- .. code-block:: python
-
- prompt = "Write a poem about a stream."
- prompt = f"\n\nHuman: {prompt}\n\nAssistant:"
- generator = anthropic.stream(prompt)
- for token in generator:
- yield token
- """
- stop = self._get_anthropic_stop(stop)
- params = {**self._default_params, **kwargs}
-
- for token in self.client.completions.create(
- prompt=self._wrap_prompt(prompt), stop_sequences=stop, stream=True, **params
- ):
- chunk = GenerationChunk(text=token.completion)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(chunk.text, chunk=chunk)
-
- async def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- r"""Call Anthropic completion_stream and return the resulting generator.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- A generator representing the stream of tokens from Anthropic.
- Example:
- .. code-block:: python
- prompt = "Write a poem about a stream."
- prompt = f"\n\nHuman: {prompt}\n\nAssistant:"
- generator = anthropic.stream(prompt)
- for token in generator:
- yield token
- """
- stop = self._get_anthropic_stop(stop)
- params = {**self._default_params, **kwargs}
-
- async for token in await self.async_client.completions.create(
- prompt=self._wrap_prompt(prompt),
- stop_sequences=stop,
- stream=True,
- **params,
- ):
- chunk = GenerationChunk(text=token.completion)
- yield chunk
- if run_manager:
- await run_manager.on_llm_new_token(chunk.text, chunk=chunk)
-
- def get_num_tokens(self, text: str) -> int:
- """Calculate number of tokens."""
- if not self.count_tokens:
- raise NameError("Please ensure the anthropic package is loaded")
- return self.count_tokens(text)
diff --git a/commune/modules/model/llm/anyscale.py b/commune/modules/model/llm/anyscale.py
deleted file mode 100644
index 810d17307..000000000
--- a/commune/modules/model/llm/anyscale.py
+++ /dev/null
@@ -1,126 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class Anyscale(LLM):
- """Anyscale Service models.
-
- To use, you should have the environment variable ``ANYSCALE_SERVICE_URL``,
- ``ANYSCALE_SERVICE_ROUTE`` and ``ANYSCALE_SERVICE_TOKEN`` set with your Anyscale
- Service, or pass it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Anyscale
- anyscale = Anyscale(anyscale_service_url="SERVICE_URL",
- anyscale_service_route="SERVICE_ROUTE",
- anyscale_service_token="SERVICE_TOKEN")
-
- # Use Ray for distributed processing
- import ray
- prompt_list=[]
- @ray.remote
- def send_query(llm, prompt):
- resp = llm(prompt)
- return resp
- futures = [send_query.remote(anyscale, prompt) for prompt in prompt_list]
- results = ray.get(futures)
- """
-
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model. Reserved for future use"""
-
- anyscale_service_url: Optional[str] = None
- anyscale_service_route: Optional[str] = None
- anyscale_service_token: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- anyscale_service_url = get_from_dict_or_env(
- values, "anyscale_service_url", "ANYSCALE_SERVICE_URL"
- )
- anyscale_service_route = get_from_dict_or_env(
- values, "anyscale_service_route", "ANYSCALE_SERVICE_ROUTE"
- )
- anyscale_service_token = get_from_dict_or_env(
- values, "anyscale_service_token", "ANYSCALE_SERVICE_TOKEN"
- )
- if anyscale_service_url.endswith("/"):
- anyscale_service_url = anyscale_service_url[:-1]
- if not anyscale_service_route.startswith("/"):
- anyscale_service_route = "/" + anyscale_service_route
- try:
- anyscale_service_endpoint = f"{anyscale_service_url}/-/routes"
- headers = {"Authorization": f"Bearer {anyscale_service_token}"}
- requests.get(anyscale_service_endpoint, headers=headers)
- except requests.exceptions.RequestException as e:
- raise ValueError(e)
-
- values["anyscale_service_url"] = anyscale_service_url
- values["anyscale_service_route"] = anyscale_service_route
- values["anyscale_service_token"] = anyscale_service_token
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "anyscale_service_url": self.anyscale_service_url,
- "anyscale_service_route": self.anyscale_service_route,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "anyscale"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Anyscale Service endpoint.
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- The string generated by the model.
- Example:
- .. code-block:: python
- response = anyscale("Tell me a joke.")
- """
-
- anyscale_service_endpoint = (
- f"{self.anyscale_service_url}{self.anyscale_service_route}"
- )
- headers = {"Authorization": f"Bearer {self.anyscale_service_token}"}
- body = {"prompt": prompt}
- resp = requests.post(anyscale_service_endpoint, headers=headers, json=body)
-
- if resp.status_code != 200:
- raise ValueError(
- f"Error returned by service, status code {resp.status_code}"
- )
- text = resp.text
-
- if stop is not None:
- # This is a bit hacky, but I can't figure out a better way to enforce
- # stop tokens when making calls to huggingface_hub.
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/aviary.py b/commune/modules/model/llm/aviary.py
deleted file mode 100644
index 8444a3a04..000000000
--- a/commune/modules/model/llm/aviary.py
+++ /dev/null
@@ -1,197 +0,0 @@
-import dataclasses
-import os
-from typing import Any, Dict, List, Mapping, Optional, Union, cast
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-TIMEOUT = 60
-
-
-@dataclasses.dataclass
-class AviaryBackend:
- """Aviary backend.
-
- Attributes:
- backend_url: The URL for the Aviary backend.
- bearer: The bearer token for the Aviary backend.
- """
-
- backend_url: str
- bearer: str
-
- def __post_init__(self) -> None:
- self.header = {"Authorization": self.bearer}
-
- @classmethod
- def from_env(cls) -> "AviaryBackend":
- aviary_url = os.getenv("AVIARY_URL")
- assert aviary_url, "AVIARY_URL must be set"
-
- aviary_token = os.getenv("AVIARY_TOKEN", "")
-
- bearer = f"Bearer {aviary_token}" if aviary_token else ""
- aviary_url += "/" if not aviary_url.endswith("/") else ""
-
- return cls(aviary_url, bearer)
-
-
-def get_models() -> List[str]:
- """List available models"""
- backend = AviaryBackend.from_env()
- request_url = backend.backend_url + "-/routes"
- response = requests.get(request_url, headers=backend.header, timeout=TIMEOUT)
- try:
- result = response.json()
- except requests.JSONDecodeError as e:
- raise RuntimeError(
- f"Error decoding JSON from {request_url}. Text response: {response.text}"
- ) from e
- result = sorted(
- [k.lstrip("/").replace("--", "/") for k in result.keys() if "--" in k]
- )
- return result
-
-
-def get_completions(
- model: str,
- prompt: str,
- use_prompt_format: bool = True,
- version: str = "",
-) -> Dict[str, Union[str, float, int]]:
- """Get completions from Aviary models."""
-
- backend = AviaryBackend.from_env()
- url = backend.backend_url + model.replace("/", "--") + "/" + version + "query"
- response = requests.post(
- url,
- headers=backend.header,
- json={"prompt": prompt, "use_prompt_format": use_prompt_format},
- timeout=TIMEOUT,
- )
- try:
- return response.json()
- except requests.JSONDecodeError as e:
- raise RuntimeError(
- f"Error decoding JSON from {url}. Text response: {response.text}"
- ) from e
-
-
-class Aviary(LLM):
- """Aviary hosted models.
-
- Aviary is a backend for hosted models. You can
- find out more about aviary at
- http://github.com/ray-project/aviary
-
- To get a list of the models supported on an
- aviary, follow the instructions on the website to
- install the aviary CLI and then use:
- `aviary models`
-
- AVIARY_URL and AVIARY_TOKEN environment variables must be set.
-
- Attributes:
- model: The name of the model to use. Defaults to "amazon/LightGPT".
- aviary_url: The URL for the Aviary backend. Defaults to None.
- aviary_token: The bearer token for the Aviary backend. Defaults to None.
- use_prompt_format: If True, the prompt template for the model will be ignored.
- Defaults to True.
- version: API version to use for Aviary. Defaults to None.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Aviary
- os.environ["AVIARY_URL"] = ""
- os.environ["AVIARY_TOKEN"] = ""
- light = Aviary(model='amazon/LightGPT')
- output = light('How do you make fried rice?')
- """
-
- model: str = "amazon/LightGPT"
- aviary_url: Optional[str] = None
- aviary_token: Optional[str] = None
- # If True the prompt template for the model will be ignored.
- use_prompt_format: bool = True
- # API version to use for Aviary
- version: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- aviary_url = get_from_dict_or_env(values, "aviary_url", "AVIARY_URL")
- aviary_token = get_from_dict_or_env(values, "aviary_token", "AVIARY_TOKEN")
-
- # Set env viarables for aviary sdk
- os.environ["AVIARY_URL"] = aviary_url
- os.environ["AVIARY_TOKEN"] = aviary_token
-
- try:
- aviary_models = get_models()
- except requests.exceptions.RequestException as e:
- raise ValueError(e)
-
- model = values.get("model")
- if model and model not in aviary_models:
- raise ValueError(f"{aviary_url} does not support model {values['model']}.")
-
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "model_name": self.model,
- "aviary_url": self.aviary_url,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return f"aviary-{self.model.replace('/', '-')}"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Aviary
- Args:
- prompt: The prompt to pass into the model.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = aviary("Tell me a joke.")
- """
- kwargs = {"use_prompt_format": self.use_prompt_format}
- if self.version:
- kwargs["version"] = self.version
-
- output = get_completions(
- model=self.model,
- prompt=prompt,
- **kwargs,
- )
-
- text = cast(str, output["generated_text"])
- if stop:
- text = enforce_stop_tokens(text, stop)
-
- return text
diff --git a/commune/modules/model/llm/azureml_endpoint.py b/commune/modules/model/llm/azureml_endpoint.py
deleted file mode 100644
index 3e7833bc9..000000000
--- a/commune/modules/model/llm/azureml_endpoint.py
+++ /dev/null
@@ -1,291 +0,0 @@
-import json
-import urllib.request
-import warnings
-from abc import abstractmethod
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import BaseModel, validator
-from langchain.utils import get_from_dict_or_env
-
-
-class AzureMLEndpointClient(object):
- """AzureML Managed Endpoint client."""
-
- def __init__(
- self, endpoint_url: str, endpoint_api_key: str, deployment_name: str = ""
- ) -> None:
- """Initialize the class."""
- if not endpoint_api_key or not endpoint_url:
- raise ValueError(
- """A key/token and REST endpoint should
- be provided to invoke the endpoint"""
- )
- self.endpoint_url = endpoint_url
- self.endpoint_api_key = endpoint_api_key
- self.deployment_name = deployment_name
-
- def call(self, body: bytes, **kwargs: Any) -> bytes:
- """call."""
-
- # The azureml-model-deployment header will force the request to go to a
- # specific deployment. Remove this header to have the request observe the
- # endpoint traffic rules.
- headers = {
- "Content-Type": "application/json",
- "Authorization": ("Bearer " + self.endpoint_api_key),
- }
- if self.deployment_name != "":
- headers["azureml-model-deployment"] = self.deployment_name
-
- req = urllib.request.Request(self.endpoint_url, body, headers)
- response = urllib.request.urlopen(req, timeout=kwargs.get("timeout", 50))
- result = response.read()
- return result
-
-
-class ContentFormatterBase:
- """Transform request and response of AzureML endpoint to match with
- required schema.
- """
-
- """
- Example:
- .. code-block:: python
-
- class ContentFormatter(ContentFormatterBase):
- content_type = "application/json"
- accepts = "application/json"
-
- def format_request_payload(
- self,
- prompt: str,
- model_kwargs: Dict
- ) -> bytes:
- input_str = json.dumps(
- {
- "inputs": {"input_string": [prompt]},
- "parameters": model_kwargs,
- }
- )
- return str.encode(input_str)
-
- def format_response_payload(self, output: str) -> str:
- response_json = json.loads(output)
- return response_json[0]["0"]
- """
- content_type: Optional[str] = "application/json"
- """The MIME type of the input data passed to the endpoint"""
-
- accepts: Optional[str] = "application/json"
- """The MIME type of the response data returned from the endpoint"""
-
- @staticmethod
- def escape_special_characters(prompt: str) -> str:
- """Escapes any special characters in `prompt`"""
- escape_map = {
- "\\": "\\\\",
- '"': '\\"',
- "\b": "\\b",
- "\f": "\\f",
- "\n": "\\n",
- "\r": "\\r",
- "\t": "\\t",
- }
-
- # Replace each occurrence of the specified characters with escaped versions
- for escape_sequence, escaped_sequence in escape_map.items():
- prompt = prompt.replace(escape_sequence, escaped_sequence)
-
- return prompt
-
- @abstractmethod
- def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
- """Formats the request body according to the input schema of
- the model. Returns bytes or seekable file like object in the
- format specified in the content_type request header.
- """
-
- @abstractmethod
- def format_response_payload(self, output: bytes) -> str:
- """Formats the response body according to the output
- schema of the model. Returns the data type that is
- received from the response.
- """
-
-
-class GPT2ContentFormatter(ContentFormatterBase):
- """Content handler for GPT2"""
-
- def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
- prompt = ContentFormatterBase.escape_special_characters(prompt)
- request_payload = json.dumps(
- {"inputs": {"input_string": [f'"{prompt}"']}, "parameters": model_kwargs}
- )
- return str.encode(request_payload)
-
- def format_response_payload(self, output: bytes) -> str:
- return json.loads(output)[0]["0"]
-
-
-class OSSContentFormatter(GPT2ContentFormatter):
- """Deprecated: Kept for backwards compatibility
-
- Content handler for LLMs from the OSS catalog."""
-
- content_formatter: Any = None
-
- def __init__(self) -> None:
- super().__init__()
- warnings.warn(
- """`OSSContentFormatter` will be deprecated in the future.
- Please use `GPT2ContentFormatter` instead.
- """
- )
-
-
-class HFContentFormatter(ContentFormatterBase):
- """Content handler for LLMs from the HuggingFace catalog."""
-
- def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
- ContentFormatterBase.escape_special_characters(prompt)
- request_payload = json.dumps(
- {"inputs": [f'"{prompt}"'], "parameters": model_kwargs}
- )
- return str.encode(request_payload)
-
- def format_response_payload(self, output: bytes) -> str:
- return json.loads(output)[0]["generated_text"]
-
-
-class DollyContentFormatter(ContentFormatterBase):
- """Content handler for the Dolly-v2-12b model"""
-
- def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
- prompt = ContentFormatterBase.escape_special_characters(prompt)
- request_payload = json.dumps(
- {
- "input_data": {"input_string": [f'"{prompt}"']},
- "parameters": model_kwargs,
- }
- )
- return str.encode(request_payload)
-
- def format_response_payload(self, output: bytes) -> str:
- return json.loads(output)[0]
-
-
-class LlamaContentFormatter(ContentFormatterBase):
- """Content formatter for LLaMa"""
-
- def format_request_payload(self, prompt: str, model_kwargs: Dict) -> bytes:
- """Formats the request according the the chosen api"""
- prompt = ContentFormatterBase.escape_special_characters(prompt)
- request_payload = json.dumps(
- {
- "input_data": {
- "input_string": [f'"{prompt}"'],
- "parameters": model_kwargs,
- }
- }
- )
- return str.encode(request_payload)
-
- def format_response_payload(self, output: bytes) -> str:
- """Formats response"""
- return json.loads(output)[0]["0"]
-
-
-class AzureMLOnlineEndpoint(LLM, BaseModel):
- """Azure ML Online Endpoint models.
-
- Example:
- .. code-block:: python
-
- azure_llm = AzureMLOnlineEndpoint(
- endpoint_url="https://..inference.ml.azure.com/score",
- endpoint_api_key="my-api-key",
- content_formatter=content_formatter,
- )
- """ # noqa: E501
-
- endpoint_url: str = ""
- """URL of pre-existing Endpoint. Should be passed to constructor or specified as
- env var `AZUREML_ENDPOINT_URL`."""
-
- endpoint_api_key: str = ""
- """Authentication Key for Endpoint. Should be passed to constructor or specified as
- env var `AZUREML_ENDPOINT_API_KEY`."""
-
- deployment_name: str = ""
- """Deployment Name for Endpoint. NOT REQUIRED to call endpoint. Should be passed
- to constructor or specified as env var `AZUREML_DEPLOYMENT_NAME`."""
-
- http_client: Any = None #: :meta private:
-
- content_formatter: Any = None
- """The content formatter that provides an input and output
- transform function to handle formats between the LLM and
- the endpoint"""
-
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
-
- @validator("http_client", always=True, allow_reuse=True)
- @classmethod
- def validate_client(cls, field_value: Any, values: Dict) -> AzureMLEndpointClient:
- """Validate that api key and python package exists in environment."""
- endpoint_key = get_from_dict_or_env(
- values, "endpoint_api_key", "AZUREML_ENDPOINT_API_KEY"
- )
- endpoint_url = get_from_dict_or_env(
- values, "endpoint_url", "AZUREML_ENDPOINT_URL"
- )
- deployment_name = get_from_dict_or_env(
- values, "deployment_name", "AZUREML_DEPLOYMENT_NAME", ""
- )
- http_client = AzureMLEndpointClient(endpoint_url, endpoint_key, deployment_name)
- return http_client
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"deployment_name": self.deployment_name},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "azureml_endpoint"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to an AzureML Managed Online endpoint.
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- The string generated by the model.
- Example:
- .. code-block:: python
- response = azureml_model("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
-
- request_payload = self.content_formatter.format_request_payload(
- prompt, _model_kwargs
- )
- response_payload = self.http_client.call(request_payload, **kwargs)
- generated_text = self.content_formatter.format_response_payload(
- response_payload
- )
- return generated_text
diff --git a/commune/modules/model/llm/baidu_qianfan_endpoint.py b/commune/modules/model/llm/baidu_qianfan_endpoint.py
deleted file mode 100644
index 8b548a7cd..000000000
--- a/commune/modules/model/llm/baidu_qianfan_endpoint.py
+++ /dev/null
@@ -1,218 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import (
- Any,
- AsyncIterator,
- Dict,
- Iterator,
- List,
- Optional,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema.output import GenerationChunk
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class QianfanLLMEndpoint(LLM):
- """Baidu Qianfan hosted open source or customized models.
-
- To use, you should have the ``qianfan`` python package installed, and
- the environment variable ``qianfan_ak`` and ``qianfan_sk`` set with
- your API key and Secret Key.
-
- ak, sk are required parameters which you could get from
- https://cloud.baidu.com/product/wenxinworkshop
-
- Example:
- .. code-block:: python
-
- from langchain.llms import QianfanLLMEndpoint
- qianfan_model = QianfanLLMEndpoint(model="ERNIE-Bot",
- endpoint="your_endpoint", qianfan_ak="your_ak", qianfan_sk="your_sk")
- """
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
-
- client: Any
-
- qianfan_ak: Optional[str] = None
- qianfan_sk: Optional[str] = None
-
- streaming: Optional[bool] = False
- """Whether to stream the results or not."""
-
- model: str = "ERNIE-Bot-turbo"
- """Model name.
- you could get from https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu
-
- preset models are mapping to an endpoint.
- `model` will be ignored if `endpoint` is set
- """
-
- endpoint: Optional[str] = None
- """Endpoint of the Qianfan LLM, required if custom model used."""
-
- request_timeout: Optional[int] = 60
- """request timeout for chat http requests"""
-
- top_p: Optional[float] = 0.8
- temperature: Optional[float] = 0.95
- penalty_score: Optional[float] = 1
- """Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo.
- In the case of other model, passing these params will not affect the result.
- """
-
- @root_validator()
- def validate_enviroment(cls, values: Dict) -> Dict:
- values["qianfan_ak"] = get_from_dict_or_env(
- values,
- "qianfan_ak",
- "QIANFAN_AK",
- )
- values["qianfan_sk"] = get_from_dict_or_env(
- values,
- "qianfan_sk",
- "QIANFAN_SK",
- )
-
- params = {
- "ak": values["qianfan_ak"],
- "sk": values["qianfan_sk"],
- "model": values["model"],
- }
- if values["endpoint"] is not None and values["endpoint"] != "":
- params["endpoint"] = values["endpoint"]
- try:
- import qianfan
-
- values["client"] = qianfan.Completion(**params)
- except ImportError:
- raise ValueError(
- "qianfan package not found, please install it with "
- "`pip install qianfan`"
- )
- return values
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- return {
- **{"endpoint": self.endpoint, "model": self.model},
- **super()._identifying_params,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "baidu-qianfan-endpoint"
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- normal_params = {
- "stream": self.streaming,
- "request_timeout": self.request_timeout,
- "top_p": self.top_p,
- "temperature": self.temperature,
- "penalty_score": self.penalty_score,
- }
-
- return {**normal_params, **self.model_kwargs}
-
- def _convert_prompt_msg_params(
- self,
- prompt: str,
- **kwargs: Any,
- ) -> dict:
- if "streaming" in kwargs:
- kwargs["stream"] = kwargs.pop("streaming")
- return {
- **{"prompt": prompt, "model": self.model},
- **self._default_params,
- **kwargs,
- }
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to an qianfan models endpoint for each generation with a prompt.
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
- response = qianfan_model("Tell me a joke.")
- """
- if self.streaming:
- completion = ""
- for chunk in self._stream(prompt, stop, run_manager, **kwargs):
- completion += chunk.text
- return completion
- params = self._convert_prompt_msg_params(prompt, **kwargs)
- response_payload = self.client.do(**params)
-
- return response_payload["result"]
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- if self.streaming:
- completion = ""
- async for chunk in self._astream(prompt, stop, run_manager, **kwargs):
- completion += chunk.text
- return completion
-
- params = self._convert_prompt_msg_params(prompt, **kwargs)
- response_payload = await self.client.ado(**params)
-
- return response_payload["result"]
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- params = self._convert_prompt_msg_params(prompt, **{**kwargs, "stream": True})
- for res in self.client.do(**params):
- if res:
- chunk = GenerationChunk(text=res["result"])
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(chunk.text)
-
- async def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- params = self._convert_prompt_msg_params(prompt, **{**kwargs, "stream": True})
- async for res in await self.client.ado(**params):
- if res:
- chunk = GenerationChunk(text=res["result"])
-
- yield chunk
- if run_manager:
- await run_manager.on_llm_new_token(chunk.text)
diff --git a/commune/modules/model/llm/bananadev.py b/commune/modules/model/llm/bananadev.py
deleted file mode 100644
index 3a984a3cb..000000000
--- a/commune/modules/model/llm/bananadev.py
+++ /dev/null
@@ -1,135 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class Banana(LLM):
- """Banana large language models.
-
- To use, you should have the ``banana-dev`` python package installed,
- and the environment variable ``BANANA_API_KEY`` set with your API key.
- This is the team API key available in the Banana dashboard.
-
- Any parameters that are valid to be passed to the call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Banana
- banana = Banana(model_key="", model_url_slug="")
- """
-
- model_key: str = ""
- """model key to use"""
-
- model_url_slug: str = ""
- """model endpoint to use"""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not
- explicitly specified."""
-
- banana_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- banana_api_key = get_from_dict_or_env(
- values, "banana_api_key", "BANANA_API_KEY"
- )
- values["banana_api_key"] = banana_api_key
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_key": self.model_key},
- **{"model_url_slug": self.model_url_slug},
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "bananadev"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to Banana endpoint."""
- try:
- from banana_dev import Client
- except ImportError:
- raise ImportError(
- "Could not import banana-dev python package. "
- "Please install it with `pip install banana-dev`."
- )
- params = self.model_kwargs or {}
- params = {**params, **kwargs}
- api_key = self.banana_api_key
- model_key = self.model_key
- model_url_slug = self.model_url_slug
- model_inputs = {
- # a json specific to your model.
- "prompt": prompt,
- **params,
- }
- model = Client(
- # Found in main dashboard
- api_key=api_key,
- # Both found in model details page
- model_key=model_key,
- url=f"https://{model_url_slug}.run.banana.dev",
- )
- response, meta = model.call("/", model_inputs)
- try:
- text = response["outputs"]
- except (KeyError, TypeError):
- raise ValueError(
- "Response should be of schema: {'outputs': 'text'}."
- "\nTo fix this:"
- "\n- fork the source repo of the Banana model"
- "\n- modify app.py to return the above schema"
- "\n- deploy that as a custom repo"
- )
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/base.py b/commune/modules/model/llm/base.py
deleted file mode 100644
index bfaa85fde..000000000
--- a/commune/modules/model/llm/base.py
+++ /dev/null
@@ -1,1078 +0,0 @@
-"""Base interface for large language models to expose."""
-from __future__ import annotations
-
-import asyncio
-import functools
-import inspect
-import json
-import logging
-import warnings
-from abc import ABC, abstractmethod
-from functools import partial
-from pathlib import Path
-from typing import (
- Any,
- AsyncIterator,
- Callable,
- Dict,
- Iterator,
- List,
- Mapping,
- Optional,
- Sequence,
- Tuple,
- Type,
- Union,
- cast,
-)
-
-import yaml
-from tenacity import (
- RetryCallState,
- before_sleep_log,
- retry,
- retry_base,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-import langchain
-from langchain.callbacks.base import BaseCallbackManager
-from langchain.callbacks.manager import (
- AsyncCallbackManager,
- AsyncCallbackManagerForLLMRun,
- CallbackManager,
- CallbackManagerForLLMRun,
- Callbacks,
-)
-from langchain.load.dump import dumpd
-from langchain.prompts.base import StringPromptValue
-from langchain.prompts.chat import ChatPromptValue
-from langchain.pydantic_v1 import Field, root_validator, validator
-from langchain.schema import (
- Generation,
- LLMResult,
- PromptValue,
- RunInfo,
-)
-from langchain.schema.language_model import BaseLanguageModel, LanguageModelInput
-from langchain.schema.messages import AIMessage, BaseMessage, get_buffer_string
-from langchain.schema.output import GenerationChunk
-from langchain.schema.runnable import RunnableConfig
-from langchain.schema.runnable.config import get_config_list
-
-logger = logging.getLogger(__name__)
-
-
-def _get_verbosity() -> bool:
- return langchain.verbose
-
-
-@functools.lru_cache
-def _log_error_once(msg: str) -> None:
- """Log an error once."""
- logger.error(msg)
-
-
-def create_base_retry_decorator(
- error_types: List[Type[BaseException]],
- max_retries: int = 1,
- run_manager: Optional[
- Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]
- ] = None,
-) -> Callable[[Any], Any]:
- """Create a retry decorator for a given LLM and provided list of error types."""
-
- _logging = before_sleep_log(logger, logging.WARNING)
-
- def _before_sleep(retry_state: RetryCallState) -> None:
- _logging(retry_state)
- if run_manager:
- if isinstance(run_manager, AsyncCallbackManagerForLLMRun):
- coro = run_manager.on_retry(retry_state)
- try:
- loop = asyncio.get_event_loop()
- if loop.is_running():
- loop.create_task(coro)
- else:
- asyncio.run(coro)
- except Exception as e:
- _log_error_once(f"Error in on_retry: {e}")
- else:
- run_manager.on_retry(retry_state)
- return None
-
- min_seconds = 4
- max_seconds = 10
- # Wait 2^x * 1 second between each retry starting with
- # 4 seconds, then up to 10 seconds, then 10 seconds afterwards
- retry_instance: "retry_base" = retry_if_exception_type(error_types[0])
- for error in error_types[1:]:
- retry_instance = retry_instance | retry_if_exception_type(error)
- return retry(
- reraise=True,
- stop=stop_after_attempt(max_retries),
- wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
- retry=retry_instance,
- before_sleep=_before_sleep,
- )
-
-
-def get_prompts(
- params: Dict[str, Any], prompts: List[str]
-) -> Tuple[Dict[int, List], str, List[int], List[str]]:
- """Get prompts that are already cached."""
- llm_string = str(sorted([(k, v) for k, v in params.items()]))
- missing_prompts = []
- missing_prompt_idxs = []
- existing_prompts = {}
- for i, prompt in enumerate(prompts):
- if langchain.llm_cache is not None:
- cache_val = langchain.llm_cache.lookup(prompt, llm_string)
- if isinstance(cache_val, list):
- existing_prompts[i] = cache_val
- else:
- missing_prompts.append(prompt)
- missing_prompt_idxs.append(i)
- return existing_prompts, llm_string, missing_prompt_idxs, missing_prompts
-
-
-def update_cache(
- existing_prompts: Dict[int, List],
- llm_string: str,
- missing_prompt_idxs: List[int],
- new_results: LLMResult,
- prompts: List[str],
-) -> Optional[dict]:
- """Update the cache and get the LLM output."""
- for i, result in enumerate(new_results.generations):
- existing_prompts[missing_prompt_idxs[i]] = result
- prompt = prompts[missing_prompt_idxs[i]]
- if langchain.llm_cache is not None:
- langchain.llm_cache.update(prompt, llm_string, result)
- llm_output = new_results.llm_output
- return llm_output
-
-
-class BaseLLM(BaseLanguageModel[str], ABC):
- """Base LLM abstract interface.
-
- It should take in a prompt and return a string."""
-
- cache: Optional[bool] = None
- verbose: bool = Field(default_factory=_get_verbosity)
- """Whether to print out response text."""
- callbacks: Callbacks = Field(default=None, exclude=True)
- callback_manager: Optional[BaseCallbackManager] = Field(default=None, exclude=True)
- tags: Optional[List[str]] = Field(default=None, exclude=True)
- """Tags to add to the run trace."""
- metadata: Optional[Dict[str, Any]] = Field(default=None, exclude=True)
- """Metadata to add to the run trace."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- arbitrary_types_allowed = True
-
- @root_validator()
- def raise_deprecation(cls, values: Dict) -> Dict:
- """Raise deprecation warning if callback_manager is used."""
- if values.get("callback_manager") is not None:
- warnings.warn(
- "callback_manager is deprecated. Please use callbacks instead.",
- DeprecationWarning,
- )
- values["callbacks"] = values.pop("callback_manager", None)
- return values
-
- @validator("verbose", pre=True, always=True)
- def set_verbose(cls, verbose: Optional[bool]) -> bool:
- """If verbose is None, set it.
-
- This allows users to pass in None as verbose to access the global setting.
- """
- if verbose is None:
- return _get_verbosity()
- else:
- return verbose
-
- # --- Runnable methods ---
-
- def _convert_input(self, input: LanguageModelInput) -> PromptValue:
- if isinstance(input, PromptValue):
- return input
- elif isinstance(input, str):
- return StringPromptValue(text=input)
- elif isinstance(input, list):
- return ChatPromptValue(messages=input)
- else:
- raise ValueError(
- f"Invalid input type {type(input)}. "
- "Must be a PromptValue, str, or list of BaseMessages."
- )
-
- def invoke(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> str:
- config = config or {}
- return (
- self.generate_prompt(
- [self._convert_input(input)],
- stop=stop,
- callbacks=config.get("callbacks"),
- tags=config.get("tags"),
- metadata=config.get("metadata"),
- run_name=config.get("run_name"),
- **kwargs,
- )
- .generations[0][0]
- .text
- )
-
- async def ainvoke(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> str:
- if type(self)._agenerate == BaseLLM._agenerate:
- # model doesn't implement async invoke, so use default implementation
- return await asyncio.get_running_loop().run_in_executor(
- None, partial(self.invoke, input, config, stop=stop, **kwargs)
- )
-
- config = config or {}
- llm_result = await self.agenerate_prompt(
- [self._convert_input(input)],
- stop=stop,
- callbacks=config.get("callbacks"),
- tags=config.get("tags"),
- metadata=config.get("metadata"),
- run_name=config.get("run_name"),
- **kwargs,
- )
- return llm_result.generations[0][0].text
-
- def batch(
- self,
- inputs: List[LanguageModelInput],
- config: Optional[Union[RunnableConfig, List[RunnableConfig]]] = None,
- *,
- return_exceptions: bool = False,
- **kwargs: Any,
- ) -> List[str]:
- if not inputs:
- return []
-
- config = get_config_list(config, len(inputs))
- max_concurrency = config[0].get("max_concurrency")
-
- if max_concurrency is None:
- try:
- llm_result = self.generate_prompt(
- [self._convert_input(input) for input in inputs],
- callbacks=[c.get("callbacks") for c in config],
- tags=[c.get("tags") for c in config],
- metadata=[c.get("metadata") for c in config],
- run_name=[c.get("run_name") for c in config],
- **kwargs,
- )
- return [g[0].text for g in llm_result.generations]
- except Exception as e:
- if return_exceptions:
- return cast(List[str], [e for _ in inputs])
- else:
- raise e
- else:
- batches = [
- inputs[i : i + max_concurrency]
- for i in range(0, len(inputs), max_concurrency)
- ]
- return [
- output
- for batch in batches
- for output in self.batch(
- batch, config=config, return_exceptions=return_exceptions, **kwargs
- )
- ]
-
- async def abatch(
- self,
- inputs: List[LanguageModelInput],
- config: Optional[Union[RunnableConfig, List[RunnableConfig]]] = None,
- *,
- return_exceptions: bool = False,
- **kwargs: Any,
- ) -> List[str]:
- if not inputs:
- return []
-
- if type(self)._agenerate == BaseLLM._agenerate:
- # model doesn't implement async batch, so use default implementation
- return await asyncio.get_running_loop().run_in_executor(
- None, partial(self.batch, **kwargs), inputs, config
- )
-
- config = get_config_list(config, len(inputs))
- max_concurrency = config[0].get("max_concurrency")
-
- if max_concurrency is None:
- try:
- llm_result = await self.agenerate_prompt(
- [self._convert_input(input) for input in inputs],
- callbacks=[c.get("callbacks") for c in config],
- tags=[c.get("tags") for c in config],
- metadata=[c.get("metadata") for c in config],
- run_name=[c.get("run_name") for c in config],
- **kwargs,
- )
- return [g[0].text for g in llm_result.generations]
- except Exception as e:
- if return_exceptions:
- return cast(List[str], [e for _ in inputs])
- else:
- raise e
- else:
- batches = [
- inputs[i : i + max_concurrency]
- for i in range(0, len(inputs), max_concurrency)
- ]
- return [
- output
- for batch in batches
- for output in await self.abatch(batch, config=config, **kwargs)
- ]
-
- def stream(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> Iterator[str]:
- if type(self)._stream == BaseLLM._stream:
- # model doesn't implement streaming, so use default implementation
- yield self.invoke(input, config=config, stop=stop, **kwargs)
- else:
- prompt = self._convert_input(input).to_string()
- config = config or {}
- params = self.dict()
- params["stop"] = stop
- params = {**params, **kwargs}
- options = {"stop": stop}
- callback_manager = CallbackManager.configure(
- config.get("callbacks"),
- self.callbacks,
- self.verbose,
- config.get("tags"),
- self.tags,
- config.get("metadata"),
- self.metadata,
- )
- (run_manager,) = callback_manager.on_llm_start(
- dumpd(self),
- [prompt],
- invocation_params=params,
- options=options,
- name=config.get("run_name"),
- )
- try:
- generation: Optional[GenerationChunk] = None
- for chunk in self._stream(
- prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- yield chunk.text
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- except BaseException as e:
- run_manager.on_llm_error(e)
- raise e
- else:
- run_manager.on_llm_end(LLMResult(generations=[[generation]]))
-
- async def astream(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> AsyncIterator[str]:
- if type(self)._astream == BaseLLM._astream:
- # model doesn't implement streaming, so use default implementation
- yield await self.ainvoke(input, config=config, stop=stop, **kwargs)
- else:
- prompt = self._convert_input(input).to_string()
- config = config or {}
- params = self.dict()
- params["stop"] = stop
- params = {**params, **kwargs}
- options = {"stop": stop}
- callback_manager = AsyncCallbackManager.configure(
- config.get("callbacks"),
- self.callbacks,
- self.verbose,
- config.get("tags"),
- self.tags,
- config.get("metadata"),
- self.metadata,
- )
- (run_manager,) = await callback_manager.on_llm_start(
- dumpd(self),
- [prompt],
- invocation_params=params,
- options=options,
- name=config.get("run_name"),
- )
- try:
- generation: Optional[GenerationChunk] = None
- async for chunk in self._astream(
- prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- yield chunk.text
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- except BaseException as e:
- await run_manager.on_llm_error(e)
- raise e
- else:
- await run_manager.on_llm_end(LLMResult(generations=[[generation]]))
-
- # --- Custom methods ---
-
- @abstractmethod
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompts."""
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompts."""
- raise NotImplementedError()
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- raise NotImplementedError()
-
- def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- raise NotImplementedError()
-
- def generate_prompt(
- self,
- prompts: List[PromptValue],
- stop: Optional[List[str]] = None,
- callbacks: Optional[Union[Callbacks, List[Callbacks]]] = None,
- **kwargs: Any,
- ) -> LLMResult:
- prompt_strings = [p.to_string() for p in prompts]
- return self.generate(prompt_strings, stop=stop, callbacks=callbacks, **kwargs)
-
- async def agenerate_prompt(
- self,
- prompts: List[PromptValue],
- stop: Optional[List[str]] = None,
- callbacks: Optional[Union[Callbacks, List[Callbacks]]] = None,
- **kwargs: Any,
- ) -> LLMResult:
- prompt_strings = [p.to_string() for p in prompts]
- return await self.agenerate(
- prompt_strings, stop=stop, callbacks=callbacks, **kwargs
- )
-
- def _generate_helper(
- self,
- prompts: List[str],
- stop: Optional[List[str]],
- run_managers: List[CallbackManagerForLLMRun],
- new_arg_supported: bool,
- **kwargs: Any,
- ) -> LLMResult:
- try:
- output = (
- self._generate(
- prompts,
- stop=stop,
- # TODO: support multiple run managers
- run_manager=run_managers[0] if run_managers else None,
- **kwargs,
- )
- if new_arg_supported
- else self._generate(prompts, stop=stop)
- )
- except BaseException as e:
- for run_manager in run_managers:
- run_manager.on_llm_error(e)
- raise e
- flattened_outputs = output.flatten()
- for manager, flattened_output in zip(run_managers, flattened_outputs):
- manager.on_llm_end(flattened_output)
- if run_managers:
- output.run = [
- RunInfo(run_id=run_manager.run_id) for run_manager in run_managers
- ]
- return output
-
- def generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- callbacks: Optional[Union[Callbacks, List[Callbacks]]] = None,
- *,
- tags: Optional[Union[List[str], List[List[str]]]] = None,
- metadata: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None,
- run_name: Optional[Union[str, List[str]]] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
- if not isinstance(prompts, list):
- raise ValueError(
- "Argument 'prompts' is expected to be of type List[str], received"
- f" argument of type {type(prompts)}."
- )
- # Create callback managers
- if (
- isinstance(callbacks, list)
- and callbacks
- and (
- isinstance(callbacks[0], (list, BaseCallbackManager))
- or callbacks[0] is None
- )
- ):
- # We've received a list of callbacks args to apply to each input
- assert len(callbacks) == len(prompts)
- assert tags is None or (
- isinstance(tags, list) and len(tags) == len(prompts)
- )
- assert metadata is None or (
- isinstance(metadata, list) and len(metadata) == len(prompts)
- )
- assert run_name is None or (
- isinstance(run_name, list) and len(run_name) == len(prompts)
- )
- callbacks = cast(List[Callbacks], callbacks)
- tags_list = cast(List[Optional[List[str]]], tags or ([None] * len(prompts)))
- metadata_list = cast(
- List[Optional[Dict[str, Any]]], metadata or ([{}] * len(prompts))
- )
- run_name_list = run_name or cast(
- List[Optional[str]], ([None] * len(prompts))
- )
- callback_managers = [
- CallbackManager.configure(
- callback,
- self.callbacks,
- self.verbose,
- tag,
- self.tags,
- meta,
- self.metadata,
- )
- for callback, tag, meta in zip(callbacks, tags_list, metadata_list)
- ]
- else:
- # We've received a single callbacks arg to apply to all inputs
- callback_managers = [
- CallbackManager.configure(
- cast(Callbacks, callbacks),
- self.callbacks,
- self.verbose,
- cast(List[str], tags),
- self.tags,
- cast(Dict[str, Any], metadata),
- self.metadata,
- )
- ] * len(prompts)
- run_name_list = [cast(Optional[str], run_name)] * len(prompts)
-
- params = self.dict()
- params["stop"] = stop
- options = {"stop": stop}
- (
- existing_prompts,
- llm_string,
- missing_prompt_idxs,
- missing_prompts,
- ) = get_prompts(params, prompts)
- disregard_cache = self.cache is not None and not self.cache
- new_arg_supported = inspect.signature(self._generate).parameters.get(
- "run_manager"
- )
- if langchain.llm_cache is None or disregard_cache:
- if self.cache is not None and self.cache:
- raise ValueError(
- "Asked to cache, but no cache found at `langchain.cache`."
- )
- run_managers = [
- callback_manager.on_llm_start(
- dumpd(self),
- [prompt],
- invocation_params=params,
- options=options,
- name=run_name,
- )[0]
- for callback_manager, prompt, run_name in zip(
- callback_managers, prompts, run_name_list
- )
- ]
- output = self._generate_helper(
- prompts, stop, run_managers, bool(new_arg_supported), **kwargs
- )
- return output
- if len(missing_prompts) > 0:
- run_managers = [
- callback_managers[idx].on_llm_start(
- dumpd(self),
- [prompts[idx]],
- invocation_params=params,
- options=options,
- name=run_name_list[idx],
- )[0]
- for idx in missing_prompt_idxs
- ]
- new_results = self._generate_helper(
- missing_prompts, stop, run_managers, bool(new_arg_supported), **kwargs
- )
- llm_output = update_cache(
- existing_prompts, llm_string, missing_prompt_idxs, new_results, prompts
- )
- run_info = (
- [RunInfo(run_id=run_manager.run_id) for run_manager in run_managers]
- if run_managers
- else None
- )
- else:
- llm_output = {}
- run_info = None
- generations = [existing_prompts[i] for i in range(len(prompts))]
- return LLMResult(generations=generations, llm_output=llm_output, run=run_info)
-
- async def _agenerate_helper(
- self,
- prompts: List[str],
- stop: Optional[List[str]],
- run_managers: List[AsyncCallbackManagerForLLMRun],
- new_arg_supported: bool,
- **kwargs: Any,
- ) -> LLMResult:
- try:
- output = (
- await self._agenerate(
- prompts,
- stop=stop,
- run_manager=run_managers[0] if run_managers else None,
- **kwargs,
- )
- if new_arg_supported
- else await self._agenerate(prompts, stop=stop)
- )
- except BaseException as e:
- await asyncio.gather(
- *[run_manager.on_llm_error(e) for run_manager in run_managers]
- )
- raise e
- flattened_outputs = output.flatten()
- await asyncio.gather(
- *[
- run_manager.on_llm_end(flattened_output)
- for run_manager, flattened_output in zip(
- run_managers, flattened_outputs
- )
- ]
- )
- if run_managers:
- output.run = [
- RunInfo(run_id=run_manager.run_id) for run_manager in run_managers
- ]
- return output
-
- async def agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- callbacks: Optional[Union[Callbacks, List[Callbacks]]] = None,
- *,
- tags: Optional[Union[List[str], List[List[str]]]] = None,
- metadata: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None,
- run_name: Optional[Union[str, List[str]]] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
- # Create callback managers
- if isinstance(callbacks, list) and (
- isinstance(callbacks[0], (list, BaseCallbackManager))
- or callbacks[0] is None
- ):
- # We've received a list of callbacks args to apply to each input
- assert len(callbacks) == len(prompts)
- assert tags is None or (
- isinstance(tags, list) and len(tags) == len(prompts)
- )
- assert metadata is None or (
- isinstance(metadata, list) and len(metadata) == len(prompts)
- )
- assert run_name is None or (
- isinstance(run_name, list) and len(run_name) == len(prompts)
- )
- callbacks = cast(List[Callbacks], callbacks)
- tags_list = cast(List[Optional[List[str]]], tags or ([None] * len(prompts)))
- metadata_list = cast(
- List[Optional[Dict[str, Any]]], metadata or ([{}] * len(prompts))
- )
- run_name_list = run_name or cast(
- List[Optional[str]], ([None] * len(prompts))
- )
- callback_managers = [
- AsyncCallbackManager.configure(
- callback,
- self.callbacks,
- self.verbose,
- tag,
- self.tags,
- meta,
- self.metadata,
- )
- for callback, tag, meta in zip(callbacks, tags_list, metadata_list)
- ]
- else:
- # We've received a single callbacks arg to apply to all inputs
- callback_managers = [
- AsyncCallbackManager.configure(
- cast(Callbacks, callbacks),
- self.callbacks,
- self.verbose,
- cast(List[str], tags),
- self.tags,
- cast(Dict[str, Any], metadata),
- self.metadata,
- )
- ] * len(prompts)
- run_name_list = [cast(Optional[str], run_name)] * len(prompts)
-
- params = self.dict()
- params["stop"] = stop
- options = {"stop": stop}
- (
- existing_prompts,
- llm_string,
- missing_prompt_idxs,
- missing_prompts,
- ) = get_prompts(params, prompts)
- disregard_cache = self.cache is not None and not self.cache
- new_arg_supported = inspect.signature(self._agenerate).parameters.get(
- "run_manager"
- )
- if langchain.llm_cache is None or disregard_cache:
- if self.cache is not None and self.cache:
- raise ValueError(
- "Asked to cache, but no cache found at `langchain.cache`."
- )
- run_managers = await asyncio.gather(
- *[
- callback_manager.on_llm_start(
- dumpd(self),
- [prompt],
- invocation_params=params,
- options=options,
- name=run_name,
- )
- for callback_manager, prompt, run_name in zip(
- callback_managers, prompts, run_name_list
- )
- ]
- )
- run_managers = [r[0] for r in run_managers]
- output = await self._agenerate_helper(
- prompts, stop, run_managers, bool(new_arg_supported), **kwargs
- )
- return output
- if len(missing_prompts) > 0:
- run_managers = await asyncio.gather(
- *[
- callback_managers[idx].on_llm_start(
- dumpd(self),
- [prompts[idx]],
- invocation_params=params,
- options=options,
- name=run_name_list[idx],
- )
- for idx in missing_prompt_idxs
- ]
- )
- run_managers = [r[0] for r in run_managers]
- new_results = await self._agenerate_helper(
- missing_prompts, stop, run_managers, bool(new_arg_supported), **kwargs
- )
- llm_output = update_cache(
- existing_prompts, llm_string, missing_prompt_idxs, new_results, prompts
- )
- run_info = (
- [RunInfo(run_id=run_manager.run_id) for run_manager in run_managers]
- if run_managers
- else None
- )
- else:
- llm_output = {}
- run_info = None
- generations = [existing_prompts[i] for i in range(len(prompts))]
- return LLMResult(generations=generations, llm_output=llm_output, run=run_info)
-
- def __call__(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- *,
- tags: Optional[List[str]] = None,
- metadata: Optional[Dict[str, Any]] = None,
- **kwargs: Any,
- ) -> str:
- """Check Cache and run the LLM on the given prompt and input."""
- if not isinstance(prompt, str):
- raise ValueError(
- "Argument `prompt` is expected to be a string. Instead found "
- f"{type(prompt)}. If you want to run the LLM on multiple prompts, use "
- "`generate` instead."
- )
- return (
- self.generate(
- [prompt],
- stop=stop,
- callbacks=callbacks,
- tags=tags,
- metadata=metadata,
- **kwargs,
- )
- .generations[0][0]
- .text
- )
-
- async def _call_async(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- callbacks: Callbacks = None,
- *,
- tags: Optional[List[str]] = None,
- metadata: Optional[Dict[str, Any]] = None,
- **kwargs: Any,
- ) -> str:
- """Check Cache and run the LLM on the given prompt and input."""
- result = await self.agenerate(
- [prompt],
- stop=stop,
- callbacks=callbacks,
- tags=tags,
- metadata=metadata,
- **kwargs,
- )
- return result.generations[0][0].text
-
- def predict(
- self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any
- ) -> str:
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- return self(text, stop=_stop, **kwargs)
-
- def predict_messages(
- self,
- messages: List[BaseMessage],
- *,
- stop: Optional[Sequence[str]] = None,
- **kwargs: Any,
- ) -> BaseMessage:
- text = get_buffer_string(messages)
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- content = self(text, stop=_stop, **kwargs)
- return AIMessage(content=content)
-
- async def apredict(
- self, text: str, *, stop: Optional[Sequence[str]] = None, **kwargs: Any
- ) -> str:
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- return await self._call_async(text, stop=_stop, **kwargs)
-
- async def apredict_messages(
- self,
- messages: List[BaseMessage],
- *,
- stop: Optional[Sequence[str]] = None,
- **kwargs: Any,
- ) -> BaseMessage:
- text = get_buffer_string(messages)
- if stop is None:
- _stop = None
- else:
- _stop = list(stop)
- content = await self._call_async(text, stop=_stop, **kwargs)
- return AIMessage(content=content)
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {}
-
- def __str__(self) -> str:
- """Get a string representation of the object for printing."""
- cls_name = f"\033[1m{self.__class__.__name__}\033[0m"
- return f"{cls_name}\nParams: {self._identifying_params}"
-
- @property
- @abstractmethod
- def _llm_type(self) -> str:
- """Return type of llm."""
-
- def dict(self, **kwargs: Any) -> Dict:
- """Return a dictionary of the LLM."""
- starter_dict = dict(self._identifying_params)
- starter_dict["_type"] = self._llm_type
- return starter_dict
-
- def save(self, file_path: Union[Path, str]) -> None:
- """Save the LLM.
-
- Args:
- file_path: Path to file to save the LLM to.
-
- Example:
- .. code-block:: python
-
- llm.save(file_path="path/llm.yaml")
- """
- # Convert file to Path object.
- if isinstance(file_path, str):
- save_path = Path(file_path)
- else:
- save_path = file_path
-
- directory_path = save_path.parent
- directory_path.mkdir(parents=True, exist_ok=True)
-
- # Fetch dictionary to save
- prompt_dict = self.dict()
-
- if save_path.suffix == ".json":
- with open(file_path, "w") as f:
- json.dump(prompt_dict, f, indent=4)
- elif save_path.suffix == ".yaml":
- with open(file_path, "w") as f:
- yaml.dump(prompt_dict, f, default_flow_style=False)
- else:
- raise ValueError(f"{save_path} must be json or yaml")
-
-
-class LLM(BaseLLM):
- """Base LLM abstract class.
-
- The purpose of this class is to expose a simpler interface for working
- with LLMs, rather than expect the user to implement the full _generate method.
- """
-
- @abstractmethod
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Run the LLM on the given prompt and input."""
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Run the LLM on the given prompt and input."""
- raise NotImplementedError()
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
- # TODO: add caching here.
- generations = []
- new_arg_supported = inspect.signature(self._call).parameters.get("run_manager")
- for prompt in prompts:
- text = (
- self._call(prompt, stop=stop, run_manager=run_manager, **kwargs)
- if new_arg_supported
- else self._call(prompt, stop=stop, **kwargs)
- )
- generations.append([Generation(text=text)])
- return LLMResult(generations=generations)
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- if type(self)._acall == LLM._acall:
- # model doesn't implement async call, so use default implementation
- return await asyncio.get_running_loop().run_in_executor(
- None, partial(self._generate, prompts, stop, run_manager, **kwargs)
- )
-
- """Run the LLM on the given prompt and input."""
- generations = []
- new_arg_supported = inspect.signature(self._acall).parameters.get("run_manager")
- for prompt in prompts:
- text = (
- await self._acall(prompt, stop=stop, run_manager=run_manager, **kwargs)
- if new_arg_supported
- else await self._acall(prompt, stop=stop, **kwargs)
- )
- generations.append([Generation(text=text)])
- return LLMResult(generations=generations)
diff --git a/commune/modules/model/llm/baseten.py b/commune/modules/model/llm/baseten.py
deleted file mode 100644
index d8f1fb4e9..000000000
--- a/commune/modules/model/llm/baseten.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field
-
-logger = logging.getLogger(__name__)
-
-
-class Baseten(LLM):
- """Baseten models.
-
- To use, you should have the ``baseten`` python package installed,
- and run ``baseten.login()`` with your Baseten API key.
-
- The required ``model`` param can be either a model id or model
- version id. Using a model version ID will result in
- slightly faster invocation.
- Any other model parameters can also
- be passed in with the format input={model_param: value, ...}
-
- The Baseten model must accept a dictionary of input with the key
- "prompt" and return a dictionary with a key "data" which maps
- to a list of response strings.
-
- Example:
- .. code-block:: python
- from langchain.llms import Baseten
- my_model = Baseten(model="MODEL_ID")
- output = my_model("prompt")
- """
-
- model: str
- input: Dict[str, Any] = Field(default_factory=dict)
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of model."""
- return "baseten"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to Baseten deployed model endpoint."""
- try:
- import baseten
- except ImportError as exc:
- raise ImportError(
- "Could not import Baseten Python package. "
- "Please install it with `pip install baseten`."
- ) from exc
-
- # get the model and version
- try:
- model = baseten.deployed_model_version_id(self.model)
- response = model.predict({"prompt": prompt, **kwargs})
- except baseten.common.core.ApiError:
- model = baseten.deployed_model_id(self.model)
- response = model.predict({"prompt": prompt, **kwargs})
- return "".join(response)
diff --git a/commune/modules/model/llm/beam.py b/commune/modules/model/llm/beam.py
deleted file mode 100644
index 20aa0d0e2..000000000
--- a/commune/modules/model/llm/beam.py
+++ /dev/null
@@ -1,273 +0,0 @@
-import base64
-import json
-import logging
-import subprocess
-import textwrap
-import time
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-DEFAULT_NUM_TRIES = 10
-DEFAULT_SLEEP_TIME = 4
-
-
-class Beam(LLM):
- """Beam API for gpt2 large language model.
-
- To use, you should have the ``beam-sdk`` python package installed,
- and the environment variable ``BEAM_CLIENT_ID`` set with your client id
- and ``BEAM_CLIENT_SECRET`` set with your client secret. Information on how
- to get this is available here: https://docs.beam.cloud/account/api-keys.
-
- The wrapper can then be called as follows, where the name, cpu, memory, gpu,
- python version, and python packages can be updated accordingly. Once deployed,
- the instance can be called.
-
- Example:
- .. code-block:: python
-
- llm = Beam(model_name="gpt2",
- name="langchain-gpt2",
- cpu=8,
- memory="32Gi",
- gpu="A10G",
- python_version="python3.8",
- python_packages=[
- "diffusers[torch]>=0.10",
- "transformers",
- "torch",
- "pillow",
- "accelerate",
- "safetensors",
- "xformers",],
- max_length=50)
- llm._deploy()
- call_result = llm._call(input)
-
- """
-
- model_name: str = ""
- name: str = ""
- cpu: str = ""
- memory: str = ""
- gpu: str = ""
- python_version: str = ""
- python_packages: List[str] = []
- max_length: str = ""
- url: str = ""
- """model endpoint to use"""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not
- explicitly specified."""
-
- beam_client_id: str = ""
- beam_client_secret: str = ""
- app_id: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- beam_client_id = get_from_dict_or_env(
- values, "beam_client_id", "BEAM_CLIENT_ID"
- )
- beam_client_secret = get_from_dict_or_env(
- values, "beam_client_secret", "BEAM_CLIENT_SECRET"
- )
- values["beam_client_id"] = beam_client_id
- values["beam_client_secret"] = beam_client_secret
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "model_name": self.model_name,
- "name": self.name,
- "cpu": self.cpu,
- "memory": self.memory,
- "gpu": self.gpu,
- "python_version": self.python_version,
- "python_packages": self.python_packages,
- "max_length": self.max_length,
- "model_kwargs": self.model_kwargs,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "beam"
-
- def app_creation(self) -> None:
- """Creates a Python file which will contain your Beam app definition."""
- script = textwrap.dedent(
- """\
- import beam
-
- # The environment your code will run on
- app = beam.App(
- name="{name}",
- cpu={cpu},
- memory="{memory}",
- gpu="{gpu}",
- python_version="{python_version}",
- python_packages={python_packages},
- )
-
- app.Trigger.RestAPI(
- inputs={{"prompt": beam.Types.String(), "max_length": beam.Types.String()}},
- outputs={{"text": beam.Types.String()}},
- handler="run.py:beam_langchain",
- )
-
- """
- )
-
- script_name = "app.py"
- with open(script_name, "w") as file:
- file.write(
- script.format(
- name=self.name,
- cpu=self.cpu,
- memory=self.memory,
- gpu=self.gpu,
- python_version=self.python_version,
- python_packages=self.python_packages,
- )
- )
-
- def run_creation(self) -> None:
- """Creates a Python file which will be deployed on beam."""
- script = textwrap.dedent(
- """
- import os
- import transformers
- from transformers import GPT2LMHeadModel, GPT2Tokenizer
-
- model_name = "{model_name}"
-
- def beam_langchain(**inputs):
- prompt = inputs["prompt"]
- length = inputs["max_length"]
-
- tokenizer = GPT2Tokenizer.from_pretrained(model_name)
- model = GPT2LMHeadModel.from_pretrained(model_name)
- encodedPrompt = tokenizer.encode(prompt, return_tensors='pt')
- outputs = model.generate(encodedPrompt, max_length=int(length),
- do_sample=True, pad_token_id=tokenizer.eos_token_id)
- output = tokenizer.decode(outputs[0], skip_special_tokens=True)
-
- print(output)
- return {{"text": output}}
-
- """
- )
-
- script_name = "run.py"
- with open(script_name, "w") as file:
- file.write(script.format(model_name=self.model_name))
-
- def _deploy(self) -> str:
- """Call to Beam."""
- try:
- import beam # type: ignore
-
- if beam.__path__ == "":
- raise ImportError
- except ImportError:
- raise ImportError(
- "Could not import beam python package. "
- "Please install it with `curl "
- "https://raw.githubusercontent.com/slai-labs"
- "/get-beam/main/get-beam.sh -sSfL | sh`."
- )
- self.app_creation()
- self.run_creation()
-
- process = subprocess.run(
- "beam deploy app.py", shell=True, capture_output=True, text=True
- )
-
- if process.returncode == 0:
- output = process.stdout
- logger.info(output)
- lines = output.split("\n")
-
- for line in lines:
- if line.startswith(" i Send requests to: https://apps.beam.cloud/"):
- self.app_id = line.split("/")[-1]
- self.url = line.split(":")[1].strip()
- return self.app_id
-
- raise ValueError(
- f"""Failed to retrieve the appID from the deployment output.
- Deployment output: {output}"""
- )
- else:
- raise ValueError(f"Deployment failed. Error: {process.stderr}")
-
- @property
- def authorization(self) -> str:
- if self.beam_client_id:
- credential_str = self.beam_client_id + ":" + self.beam_client_secret
- else:
- credential_str = self.beam_client_secret
- return base64.b64encode(credential_str.encode()).decode()
-
- def _call(
- self,
- prompt: str,
- stop: Optional[list] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to Beam."""
- url = "https://apps.beam.cloud/" + self.app_id if self.app_id else self.url
- payload = {"prompt": prompt, "max_length": self.max_length}
- payload.update(kwargs)
- headers = {
- "Accept": "*/*",
- "Accept-Encoding": "gzip, deflate",
- "Authorization": "Basic " + self.authorization,
- "Connection": "keep-alive",
- "Content-Type": "application/json",
- }
-
- for _ in range(DEFAULT_NUM_TRIES):
- request = requests.post(url, headers=headers, data=json.dumps(payload))
- if request.status_code == 200:
- return request.json()["text"]
- time.sleep(DEFAULT_SLEEP_TIME)
- logger.warning("Unable to successfully call model.")
- return ""
diff --git a/commune/modules/model/llm/bedrock.py b/commune/modules/model/llm/bedrock.py
deleted file mode 100644
index 7d07f9266..000000000
--- a/commune/modules/model/llm/bedrock.py
+++ /dev/null
@@ -1,335 +0,0 @@
-import json
-from abc import ABC
-from typing import Any, Dict, Iterator, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import BaseModel, Extra, root_validator
-from langchain.schema.output import GenerationChunk
-
-
-class LLMInputOutputAdapter:
- """Adapter class to prepare the inputs from Langchain to a format
- that LLM model expects.
-
- It also provides helper function to extract
- the generated text from the model response."""
-
- provider_to_output_key_map = {
- "anthropic": "completion",
- "amazon": "outputText",
- }
-
- @classmethod
- def prepare_input(
- cls, provider: str, prompt: str, model_kwargs: Dict[str, Any]
- ) -> Dict[str, Any]:
- input_body = {**model_kwargs}
- if provider == "anthropic" or provider == "ai21":
- input_body["prompt"] = prompt
- elif provider == "amazon":
- input_body = dict()
- input_body["inputText"] = prompt
- input_body["textGenerationConfig"] = {**model_kwargs}
- else:
- input_body["inputText"] = prompt
-
- if provider == "anthropic" and "max_tokens_to_sample" not in input_body:
- input_body["max_tokens_to_sample"] = 256
-
- return input_body
-
- @classmethod
- def prepare_output(cls, provider: str, response: Any) -> str:
- if provider == "anthropic":
- response_body = json.loads(response.get("body").read().decode())
- return response_body.get("completion")
- else:
- response_body = json.loads(response.get("body").read())
-
- if provider == "ai21":
- return response_body.get("completions")[0].get("data").get("text")
- else:
- return response_body.get("results")[0].get("outputText")
-
- @classmethod
- def prepare_output_stream(
- cls, provider: str, response: Any, stop: Optional[List[str]] = None
- ) -> Iterator[GenerationChunk]:
- stream = response.get("body")
-
- if not stream:
- return
-
- if provider not in cls.provider_to_output_key_map:
- raise ValueError(
- f"Unknown streaming response output key for provider: {provider}"
- )
-
- for event in stream:
- chunk = event.get("chunk")
- if chunk:
- chunk_obj = json.loads(chunk.get("bytes").decode())
-
- # chunk obj format varies with provider
- yield GenerationChunk(
- text=chunk_obj[cls.provider_to_output_key_map[provider]]
- )
-
-
-class BedrockBase(BaseModel, ABC):
- client: Any #: :meta private:
-
- region_name: Optional[str] = None
- """The aws region e.g., `us-west-2`. Fallsback to AWS_DEFAULT_REGION env variable
- or region specified in ~/.aws/config in case it is not provided here.
- """
-
- credentials_profile_name: Optional[str] = None
- """The name of the profile in the ~/.aws/credentials or ~/.aws/config files, which
- has either access keys or role information specified.
- If not specified, the default credential profile or, if on an EC2 instance,
- credentials from IMDS will be used.
- See: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html
- """
-
- model_id: str
- """Id of the model to call, e.g., amazon.titan-tg1-large, this is
- equivalent to the modelId property in the list-foundation-models api"""
-
- model_kwargs: Optional[Dict] = None
- """Key word arguments to pass to the model."""
-
- endpoint_url: Optional[str] = None
- """Needed if you don't want to default to us-east-1 endpoint"""
-
- streaming: bool = False
- """Whether to stream the results."""
-
- provider_stop_sequence_key_name_map: Mapping[str, str] = {
- "anthropic": "stop_sequences",
- "amazon": "stopSequences",
- "ai21": "stop_sequences",
- }
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that AWS credentials to and python package exists in environment."""
-
- # Skip creating new client if passed in constructor
- if values["client"] is not None:
- return values
-
- try:
- import boto3
-
- if values["credentials_profile_name"] is not None:
- session = boto3.Session(profile_name=values["credentials_profile_name"])
- else:
- # use default credentials
- session = boto3.Session()
-
- client_params = {}
- if values["region_name"]:
- client_params["region_name"] = values["region_name"]
- if values["endpoint_url"]:
- client_params["endpoint_url"] = values["endpoint_url"]
-
- values["client"] = session.client("bedrock", **client_params)
-
- except ImportError:
- raise ModuleNotFoundError(
- "Could not import boto3 python package. "
- "Please install it with `pip install boto3`."
- )
- except Exception as e:
- raise ValueError(
- "Could not load credentials to authenticate with AWS client. "
- "Please check that credentials in the specified "
- "profile name are valid."
- ) from e
-
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"model_kwargs": _model_kwargs},
- }
-
- def _get_provider(self) -> str:
- return self.model_id.split(".")[0]
-
- def _prepare_input_and_invoke(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- _model_kwargs = self.model_kwargs or {}
-
- provider = self._get_provider()
- params = {**_model_kwargs, **kwargs}
- input_body = LLMInputOutputAdapter.prepare_input(provider, prompt, params)
- body = json.dumps(input_body)
- accept = "application/json"
- contentType = "application/json"
-
- try:
- response = self.client.invoke_model(
- body=body, modelId=self.model_id, accept=accept, contentType=contentType
- )
- text = LLMInputOutputAdapter.prepare_output(provider, response)
-
- except Exception as e:
- raise ValueError(f"Error raised by bedrock service: {e}")
-
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
-
- return text
-
- def _prepare_input_and_invoke_stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- _model_kwargs = self.model_kwargs or {}
- provider = self._get_provider()
-
- if stop:
- if provider not in self.provider_stop_sequence_key_name_map:
- raise ValueError(
- f"Stop sequence key name for {provider} is not supported."
- )
-
- # stop sequence from _generate() overrides
- # stop sequences in the class attribute
- _model_kwargs[
- self.provider_stop_sequence_key_name_map.get(provider),
- ] = stop
-
- params = {**_model_kwargs, **kwargs}
- input_body = LLMInputOutputAdapter.prepare_input(provider, prompt, params)
- body = json.dumps(input_body)
-
- try:
- response = self.client.invoke_model_with_response_stream(
- body=body,
- modelId=self.model_id,
- accept="application/json",
- contentType="application/json",
- )
- except Exception as e:
- raise ValueError(f"Error raised by bedrock service: {e}")
-
- for chunk in LLMInputOutputAdapter.prepare_output_stream(
- provider, response, stop
- ):
- yield chunk
- if run_manager is not None:
- run_manager.on_llm_new_token(chunk.text, chunk=chunk)
-
-
-class Bedrock(LLM, BedrockBase):
- """Bedrock models.
-
- To authenticate, the AWS client uses the following methods to
- automatically load credentials:
- https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html
-
- If a specific credential profile should be used, you must pass
- the name of the profile from the ~/.aws/credentials file that is to be used.
-
- Make sure the credentials / roles used have the required policies to
- access the Bedrock service.
- """
-
- """
- Example:
- .. code-block:: python
-
- from bedrock_langchain.bedrock_llm import BedrockLLM
-
- llm = BedrockLLM(
- credentials_profile_name="default",
- model_id="amazon.titan-tg1-large",
- streaming=True
- )
-
- """
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "amazon_bedrock"
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- """Call out to Bedrock service with streaming.
-
- Args:
- prompt (str): The prompt to pass into the model
- stop (Optional[List[str]], optional): Stop sequences. These will
- override any stop sequences in the `model_kwargs` attribute.
- Defaults to None.
- run_manager (Optional[CallbackManagerForLLMRun], optional): Callback
- run managers used to process the output. Defaults to None.
-
- Returns:
- Iterator[GenerationChunk]: Generator that yields the streamed responses.
-
- Yields:
- Iterator[GenerationChunk]: Responses from the model.
- """
- return self._prepare_input_and_invoke_stream(
- prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
- )
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Bedrock service model.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = llm("Tell me a joke.")
- """
-
- if self.streaming:
- completion = ""
- for chunk in self._stream(
- prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- completion += chunk.text
- return completion
-
- return self._prepare_input_and_invoke(prompt=prompt, stop=stop, **kwargs)
diff --git a/commune/modules/model/llm/bittensor.py b/commune/modules/model/llm/bittensor.py
deleted file mode 100644
index 883651439..000000000
--- a/commune/modules/model/llm/bittensor.py
+++ /dev/null
@@ -1,173 +0,0 @@
-import http.client
-import json
-import ssl
-from typing import Any, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-
-
-class NIBittensorLLM(LLM):
- """
- NIBittensorLLM is created by Neural Internet (https://neuralinternet.ai/),
- powered by Bittensor, a decentralized network full of different AI models.
-
- To analyze API_KEYS and logs of your usage visit
- https://api.neuralinternet.ai/api-keys
- https://api.neuralinternet.ai/logs
-
- Example:
- .. code-block:: python
-
- from langchain.llms import NIBittensorLLM
- llm = NIBittensorLLM()
- """
-
- system_prompt: Optional[str]
- """Provide system prompt that you want to supply it to model before every prompt"""
-
- top_responses: Optional[int] = 0
- """Provide top_responses to get Top N miner responses on one request.May get delayed
- Don't use in Production"""
-
- @property
- def _llm_type(self) -> str:
- return "NIBittensorLLM"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """
- Wrapper around the bittensor top miner models. Its built by Neural Internet.
-
- Call the Neural Internet's BTVEP Server and return the output.
-
- Parameters (optional):
- system_prompt(str): A system prompt defining how your model should respond.
- top_responses(int): Total top miner responses to retrieve from Bittensor
- protocol.
-
- Return:
- The generated response(s).
-
- Example:
- .. code-block:: python
-
- from langchain.llms import NIBittensorLLM
- llm = NIBittensorLLM(system_prompt="Act like you are programmer with \
- 5+ years of experience.")
- """
-
- # Creating HTTPS connection with SSL
- context = ssl.create_default_context()
- context.check_hostname = True
- conn = http.client.HTTPSConnection("test.neuralinternet.ai", context=context)
-
- # Sanitizing User Input before passing to API.
- if isinstance(self.top_responses, int):
- top_n = min(100, self.top_responses)
- else:
- top_n = 0
-
- default_prompt = "You are an assistant which is created by Neural Internet(NI) \
- in decentralized network named as a Bittensor."
- if self.system_prompt is None:
- system_prompt = (
- default_prompt
- + " Your task is to provide accurate response based on user prompt"
- )
- else:
- system_prompt = default_prompt + str(self.system_prompt)
-
- # Retrieving API KEY to pass into header of each request
- conn.request("GET", "/admin/api-keys/")
- api_key_response = conn.getresponse()
- api_keys_data = (
- api_key_response.read().decode("utf-8").replace("\n", "").replace("\t", "")
- )
- api_keys_json = json.loads(api_keys_data)
- api_key = api_keys_json[0]["api_key"]
-
- # Creating Header and getting top benchmark miner uids
- headers = {
- "Content-Type": "application/json",
- "Authorization": f"Bearer {api_key}",
- "Endpoint-Version": "2023-05-19",
- }
- conn.request("GET", "/top_miner_uids", headers=headers)
- miner_response = conn.getresponse()
- miner_data = (
- miner_response.read().decode("utf-8").replace("\n", "").replace("\t", "")
- )
- uids = json.loads(miner_data)
-
- # Condition for benchmark miner response
- if isinstance(uids, list) and uids and not top_n:
- for uid in uids:
- try:
- payload = json.dumps(
- {
- "uids": [uid],
- "messages": [
- {"role": "system", "content": system_prompt},
- {"role": "user", "content": prompt},
- ],
- }
- )
-
- conn.request("POST", "/chat", payload, headers)
- init_response = conn.getresponse()
- init_data = (
- init_response.read()
- .decode("utf-8")
- .replace("\n", "")
- .replace("\t", "")
- )
- init_json = json.loads(init_data)
- if "choices" not in init_json:
- continue
- reply = init_json["choices"][0]["message"]["content"]
- conn.close()
- return reply
- except Exception:
- continue
-
- # For top miner based on bittensor response
- try:
- payload = json.dumps(
- {
- "top_n": top_n,
- "messages": [
- {"role": "system", "content": system_prompt},
- {"role": "user", "content": prompt},
- ],
- }
- )
-
- conn.request("POST", "/chat", payload, headers)
- response = conn.getresponse()
- utf_string = (
- response.read().decode("utf-8").replace("\n", "").replace("\t", "")
- )
- if top_n:
- conn.close()
- return utf_string
- json_resp = json.loads(utf_string)
- reply = json_resp["choices"][0]["message"]["content"]
- conn.close()
- return reply
- except Exception as e:
- conn.request("GET", f"/error_msg?e={e}&p={prompt}", headers=headers)
- return "Sorry I am unable to provide response now, Please try again later."
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "system_prompt": self.system_prompt,
- "top_responses": self.top_responses,
- }
diff --git a/commune/modules/model/llm/cerebriumai.py b/commune/modules/model/llm/cerebriumai.py
deleted file mode 100644
index 9b8a55eb2..000000000
--- a/commune/modules/model/llm/cerebriumai.py
+++ /dev/null
@@ -1,111 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class CerebriumAI(LLM):
- """CerebriumAI large language models.
-
- To use, you should have the ``cerebrium`` python package installed, and the
- environment variable ``CEREBRIUMAI_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import CerebriumAI
- cerebrium = CerebriumAI(endpoint_url="")
-
- """
-
- endpoint_url: str = ""
- """model endpoint to use"""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not
- explicitly specified."""
-
- cerebriumai_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- cerebriumai_api_key = get_from_dict_or_env(
- values, "cerebriumai_api_key", "CEREBRIUMAI_API_KEY"
- )
- values["cerebriumai_api_key"] = cerebriumai_api_key
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"endpoint_url": self.endpoint_url},
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "cerebriumai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to CerebriumAI endpoint."""
- try:
- from cerebrium import model_api_request
- except ImportError:
- raise ValueError(
- "Could not import cerebrium python package. "
- "Please install it with `pip install cerebrium`."
- )
-
- params = self.model_kwargs or {}
- response = model_api_request(
- self.endpoint_url,
- {"prompt": prompt, **params, **kwargs},
- self.cerebriumai_api_key,
- )
- text = response["data"]["result"]
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/chatglm.py b/commune/modules/model/llm/chatglm.py
deleted file mode 100644
index 232f2f9af..000000000
--- a/commune/modules/model/llm/chatglm.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import logging
-from typing import Any, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-
-logger = logging.getLogger(__name__)
-
-
-class ChatGLM(LLM):
- """ChatGLM LLM service.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import ChatGLM
- endpoint_url = (
- "http://127.0.0.1:8000"
- )
- ChatGLM_llm = ChatGLM(
- endpoint_url=endpoint_url
- )
- """
-
- endpoint_url: str = "http://127.0.0.1:8000/"
- """Endpoint URL to use."""
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
- max_token: int = 20000
- """Max token allowed to pass to the model."""
- temperature: float = 0.1
- """LLM model temperature from 0 to 10."""
- history: List[List] = []
- """History of the conversation"""
- top_p: float = 0.7
- """Top P for nucleus sampling from 0 to 1"""
- with_history: bool = False
- """Whether to use history or not"""
-
- @property
- def _llm_type(self) -> str:
- return "chat_glm"
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"endpoint_url": self.endpoint_url},
- **{"model_kwargs": _model_kwargs},
- }
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to a ChatGLM LLM inference endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = chatglm_llm("Who are you?")
- """
-
- _model_kwargs = self.model_kwargs or {}
-
- # HTTP headers for authorization
- headers = {"Content-Type": "application/json"}
-
- payload = {
- "prompt": prompt,
- "temperature": self.temperature,
- "history": self.history,
- "max_length": self.max_token,
- "top_p": self.top_p,
- }
- payload.update(_model_kwargs)
- payload.update(kwargs)
-
- logger.debug(f"ChatGLM payload: {payload}")
-
- # call api
- try:
- response = requests.post(self.endpoint_url, headers=headers, json=payload)
- except requests.exceptions.RequestException as e:
- raise ValueError(f"Error raised by inference endpoint: {e}")
-
- logger.debug(f"ChatGLM response: {response}")
-
- if response.status_code != 200:
- raise ValueError(f"Failed with response: {response}")
-
- try:
- parsed_response = response.json()
-
- # Check if response content does exists
- if isinstance(parsed_response, dict):
- content_keys = "response"
- if content_keys in parsed_response:
- text = parsed_response[content_keys]
- else:
- raise ValueError(f"No content in response : {parsed_response}")
- else:
- raise ValueError(f"Unexpected response type: {parsed_response}")
-
- except requests.exceptions.JSONDecodeError as e:
- raise ValueError(
- f"Error raised during decoding response from inference endpoint: {e}."
- f"\nResponse: {response.text}"
- )
-
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- if self.with_history:
- self.history = self.history + [[None, parsed_response["response"]]]
- return text
diff --git a/commune/modules/model/llm/clarifai.py b/commune/modules/model/llm/clarifai.py
deleted file mode 100644
index 0b1dea439..000000000
--- a/commune/modules/model/llm/clarifai.py
+++ /dev/null
@@ -1,245 +0,0 @@
-import logging
-from typing import Any, Dict, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.schema import Generation, LLMResult
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class Clarifai(LLM):
- """Clarifai large language models.
-
- To use, you should have an account on the Clarifai platform,
- the ``clarifai`` python package installed, and the
- environment variable ``CLARIFAI_PAT`` set with your PAT key,
- or pass it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Clarifai
- clarifai_llm = Clarifai(pat=CLARIFAI_PAT, \
- user_id=USER_ID, app_id=APP_ID, model_id=MODEL_ID)
- """
-
- stub: Any #: :meta private:
- userDataObject: Any
-
- model_id: Optional[str] = None
- """Model id to use."""
-
- model_version_id: Optional[str] = None
- """Model version id to use."""
-
- app_id: Optional[str] = None
- """Clarifai application id to use."""
-
- user_id: Optional[str] = None
- """Clarifai user id to use."""
-
- pat: Optional[str] = None
-
- api_base: str = "https://api.clarifai.com"
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that we have all required info to access Clarifai
- platform and python package exists in environment."""
- values["pat"] = get_from_dict_or_env(values, "pat", "CLARIFAI_PAT")
- user_id = values.get("user_id")
- app_id = values.get("app_id")
- model_id = values.get("model_id")
-
- if values["pat"] is None:
- raise ValueError("Please provide a pat.")
- if user_id is None:
- raise ValueError("Please provide a user_id.")
- if app_id is None:
- raise ValueError("Please provide a app_id.")
- if model_id is None:
- raise ValueError("Please provide a model_id.")
-
- try:
- from clarifai.auth.helper import ClarifaiAuthHelper
- from clarifai.client import create_stub
- except ImportError:
- raise ImportError(
- "Could not import clarifai python package. "
- "Please install it with `pip install clarifai`."
- )
- auth = ClarifaiAuthHelper(
- user_id=user_id,
- app_id=app_id,
- pat=values["pat"],
- base=values["api_base"],
- )
- values["userDataObject"] = auth.get_user_app_id_proto()
- values["stub"] = create_stub(auth)
-
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Clarifai API."""
- return {}
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {
- **{
- "user_id": self.user_id,
- "app_id": self.app_id,
- "model_id": self.model_id,
- }
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "clarifai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Clarfai's PostModelOutputs endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = clarifai_llm("Tell me a joke.")
- """
-
- try:
- from clarifai_grpc.grpc.api import (
- resources_pb2,
- service_pb2,
- )
- from clarifai_grpc.grpc.api.status import status_code_pb2
- except ImportError:
- raise ImportError(
- "Could not import clarifai python package. "
- "Please install it with `pip install clarifai`."
- )
-
- # The userDataObject is created in the overview and
- # is required when using a PAT
- # If version_id None, Defaults to the latest model version
- post_model_outputs_request = service_pb2.PostModelOutputsRequest(
- user_app_id=self.userDataObject,
- model_id=self.model_id,
- version_id=self.model_version_id,
- inputs=[
- resources_pb2.Input(
- data=resources_pb2.Data(text=resources_pb2.Text(raw=prompt))
- )
- ],
- )
- post_model_outputs_response = self.stub.PostModelOutputs(
- post_model_outputs_request
- )
-
- if post_model_outputs_response.status.code != status_code_pb2.SUCCESS:
- logger.error(post_model_outputs_response.status)
- first_model_failure = (
- post_model_outputs_response.outputs[0].status
- if len(post_model_outputs_response.outputs)
- else None
- )
- raise Exception(
- f"Post model outputs failed, status: "
- f"{post_model_outputs_response.status}, first output failure: "
- f"{first_model_failure}"
- )
-
- text = post_model_outputs_response.outputs[0].data.text.raw
-
- # In order to make this consistent with other endpoints, we strip them.
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
-
- try:
- from clarifai_grpc.grpc.api import (
- resources_pb2,
- service_pb2,
- )
- from clarifai_grpc.grpc.api.status import status_code_pb2
- except ImportError:
- raise ImportError(
- "Could not import clarifai python package. "
- "Please install it with `pip install clarifai`."
- )
-
- # TODO: add caching here.
- generations = []
- batch_size = 32
- for i in range(0, len(prompts), batch_size):
- batch = prompts[i : i + batch_size]
- post_model_outputs_request = service_pb2.PostModelOutputsRequest(
- user_app_id=self.userDataObject,
- model_id=self.model_id,
- version_id=self.model_version_id,
- inputs=[
- resources_pb2.Input(
- data=resources_pb2.Data(text=resources_pb2.Text(raw=prompt))
- )
- for prompt in batch
- ],
- )
- post_model_outputs_response = self.stub.PostModelOutputs(
- post_model_outputs_request
- )
-
- if post_model_outputs_response.status.code != status_code_pb2.SUCCESS:
- logger.error(post_model_outputs_response.status)
- first_model_failure = (
- post_model_outputs_response.outputs[0].status
- if len(post_model_outputs_response.outputs)
- else None
- )
- raise Exception(
- f"Post model outputs failed, status: "
- f"{post_model_outputs_response.status}, first output failure: "
- f"{first_model_failure}"
- )
-
- for output in post_model_outputs_response.outputs:
- if stop is not None:
- text = enforce_stop_tokens(output.data.text.raw, stop)
- else:
- text = output.data.text.raw
-
- generations.append([Generation(text=text)])
-
- return LLMResult(generations=generations)
diff --git a/commune/modules/model/llm/cohere.py b/commune/modules/model/llm/cohere.py
deleted file mode 100644
index 257a69c9f..000000000
--- a/commune/modules/model/llm/cohere.py
+++ /dev/null
@@ -1,230 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import Any, Callable, Dict, List, Optional
-
-from tenacity import (
- before_sleep_log,
- retry,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-def _create_retry_decorator(llm: Cohere) -> Callable[[Any], Any]:
- import cohere
-
- min_seconds = 4
- max_seconds = 10
- # Wait 2^x * 1 second between each retry starting with
- # 4 seconds, then up to 10 seconds, then 10 seconds afterwards
- return retry(
- reraise=True,
- stop=stop_after_attempt(llm.max_retries),
- wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
- retry=(retry_if_exception_type(cohere.error.CohereError)),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
-
-def completion_with_retry(llm: Cohere, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm)
-
- @retry_decorator
- def _completion_with_retry(**kwargs: Any) -> Any:
- return llm.client.generate(**kwargs)
-
- return _completion_with_retry(**kwargs)
-
-
-def acompletion_with_retry(llm: Cohere, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm)
-
- @retry_decorator
- async def _completion_with_retry(**kwargs: Any) -> Any:
- return await llm.async_client.generate(**kwargs)
-
- return _completion_with_retry(**kwargs)
-
-
-class Cohere(LLM):
- """Cohere large language models.
-
- To use, you should have the ``cohere`` python package installed, and the
- environment variable ``COHERE_API_KEY`` set with your API key, or pass
- it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Cohere
- cohere = Cohere(model="gptd-instruct-tft", cohere_api_key="my-api-key")
- """
-
- client: Any #: :meta private:
- async_client: Any #: :meta private:
- model: Optional[str] = None
- """Model name to use."""
-
- max_tokens: int = 256
- """Denotes the number of tokens to predict per generation."""
-
- temperature: float = 0.75
- """A non-negative float that tunes the degree of randomness in generation."""
-
- k: int = 0
- """Number of most likely tokens to consider at each step."""
-
- p: int = 1
- """Total probability mass of tokens to consider at each step."""
-
- frequency_penalty: float = 0.0
- """Penalizes repeated tokens according to frequency. Between 0 and 1."""
-
- presence_penalty: float = 0.0
- """Penalizes repeated tokens. Between 0 and 1."""
-
- truncate: Optional[str] = None
- """Specify how the client handles inputs longer than the maximum token
- length: Truncate from START, END or NONE"""
-
- max_retries: int = 10
- """Maximum number of retries to make when generating."""
-
- cohere_api_key: Optional[str] = None
-
- stop: Optional[List[str]] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- cohere_api_key = get_from_dict_or_env(
- values, "cohere_api_key", "COHERE_API_KEY"
- )
- try:
- import cohere
-
- values["client"] = cohere.Client(cohere_api_key)
- values["async_client"] = cohere.AsyncClient(cohere_api_key)
- except ImportError:
- raise ImportError(
- "Could not import cohere python package. "
- "Please install it with `pip install cohere`."
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Cohere API."""
- return {
- "max_tokens": self.max_tokens,
- "temperature": self.temperature,
- "k": self.k,
- "p": self.p,
- "frequency_penalty": self.frequency_penalty,
- "presence_penalty": self.presence_penalty,
- "truncate": self.truncate,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model": self.model}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "cohere"
-
- def _invocation_params(self, stop: Optional[List[str]], **kwargs: Any) -> dict:
- params = self._default_params
- if self.stop is not None and stop is not None:
- raise ValueError("`stop` found in both the input and default params.")
- elif self.stop is not None:
- params["stop_sequences"] = self.stop
- else:
- params["stop_sequences"] = stop
- return {**params, **kwargs}
-
- def _process_response(self, response: Any, stop: Optional[List[str]]) -> str:
- text = response.generations[0].text
- # If stop tokens are provided, Cohere's endpoint returns them.
- # In order to make this consistent with other endpoints, we strip them.
- if stop:
- text = enforce_stop_tokens(text, stop)
- return text
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Cohere's generate endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = cohere("Tell me a joke.")
- """
- params = self._invocation_params(stop, **kwargs)
- response = completion_with_retry(
- self, model=self.model, prompt=prompt, **params
- )
- _stop = params.get("stop_sequences")
- return self._process_response(response, _stop)
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Async call out to Cohere's generate endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = await cohere("Tell me a joke.")
- """
- params = self._invocation_params(stop, **kwargs)
- response = await acompletion_with_retry(
- self, model=self.model, prompt=prompt, **params
- )
- _stop = params.get("stop_sequences")
- return self._process_response(response, _stop)
diff --git a/commune/modules/model/llm/ctransformers.py b/commune/modules/model/llm/ctransformers.py
deleted file mode 100644
index ed859a1c8..000000000
--- a/commune/modules/model/llm/ctransformers.py
+++ /dev/null
@@ -1,140 +0,0 @@
-from functools import partial
-from typing import Any, Dict, List, Optional, Sequence
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import root_validator
-
-
-class CTransformers(LLM):
- """C Transformers LLM models.
-
- To use, you should have the ``ctransformers`` python package installed.
- See https://github.com/marella/ctransformers
-
- Example:
- .. code-block:: python
-
- from langchain.llms import CTransformers
-
- llm = CTransformers(model="/path/to/ggml-gpt-2.bin", model_type="gpt2")
- """
-
- client: Any #: :meta private:
-
- model: str
- """The path to a model file or directory or the name of a Hugging Face Hub
- model repo."""
-
- model_type: Optional[str] = None
- """The model type."""
-
- model_file: Optional[str] = None
- """The name of the model file in repo or directory."""
-
- config: Optional[Dict[str, Any]] = None
- """The config parameters.
- See https://github.com/marella/ctransformers#config"""
-
- lib: Optional[str] = None
- """The path to a shared library or one of `avx2`, `avx`, `basic`."""
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {
- "model": self.model,
- "model_type": self.model_type,
- "model_file": self.model_file,
- "config": self.config,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "ctransformers"
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that ``ctransformers`` package is installed."""
- try:
- from ctransformers import AutoModelForCausalLM
- except ImportError:
- raise ImportError(
- "Could not import `ctransformers` package. "
- "Please install it with `pip install ctransformers`"
- )
-
- config = values["config"] or {}
- values["client"] = AutoModelForCausalLM.from_pretrained(
- values["model"],
- model_type=values["model_type"],
- model_file=values["model_file"],
- lib=values["lib"],
- **config,
- )
- return values
-
- def _call(
- self,
- prompt: str,
- stop: Optional[Sequence[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Generate text from a prompt.
-
- Args:
- prompt: The prompt to generate text from.
- stop: A list of sequences to stop generation when encountered.
-
- Returns:
- The generated text.
-
- Example:
- .. code-block:: python
-
- response = llm("Tell me a joke.")
- """
- text = []
- _run_manager = run_manager or CallbackManagerForLLMRun.get_noop_manager()
- for chunk in self.client(prompt, stop=stop, stream=True):
- text.append(chunk)
- _run_manager.on_llm_new_token(chunk, verbose=self.verbose)
- return "".join(text)
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Asynchronous Call out to CTransformers generate method.
- Very helpful when streaming (like with websockets!)
-
- Args:
- prompt: The prompt to pass into the model.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
- response = llm("Once upon a time, ")
- """
- text_callback = None
- if run_manager:
- text_callback = partial(run_manager.on_llm_new_token, verbose=self.verbose)
-
- text = ""
- for token in self.client(prompt, stop=stop, stream=True):
- if text_callback:
- await text_callback(token)
- text += token
-
- return text
diff --git a/commune/modules/model/llm/ctranslate2.py b/commune/modules/model/llm/ctranslate2.py
deleted file mode 100644
index b6180d674..000000000
--- a/commune/modules/model/llm/ctranslate2.py
+++ /dev/null
@@ -1,128 +0,0 @@
-from typing import Any, Dict, List, Optional, Union
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import BaseLLM
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema.output import Generation, LLMResult
-
-
-class CTranslate2(BaseLLM):
- """CTranslate2 language model."""
-
- model_path: str = ""
- """Path to the CTranslate2 model directory."""
-
- tokenizer_name: str = ""
- """Name of the original Hugging Face model needed to load the proper tokenizer."""
-
- device: str = "cpu"
- """Device to use (possible values are: cpu, cuda, auto)."""
-
- device_index: Union[int, List[int]] = 0
- """Device IDs where to place this generator on."""
-
- compute_type: Union[str, Dict[str, str]] = "default"
- """
- Model computation type or a dictionary mapping a device name to the computation type
- (possible values are: default, auto, int8, int8_float32, int8_float16,
- int8_bfloat16, int16, float16, bfloat16, float32).
- """
-
- max_length: int = 512
- """Maximum generation length."""
-
- sampling_topk: int = 1
- """Randomly sample predictions from the top K candidates."""
-
- sampling_topp: float = 1
- """Keep the most probable tokens whose cumulative probability exceeds this value."""
-
- sampling_temperature: float = 1
- """Sampling temperature to generate more random samples."""
-
- client: Any #: :meta private:
-
- tokenizer: Any #: :meta private:
-
- ctranslate2_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """
- Holds any model parameters valid for `ctranslate2.Generator` call not
- explicitly specified.
- """
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that python package exists in environment."""
-
- try:
- import ctranslate2
- except ImportError:
- raise ImportError(
- "Could not import ctranslate2 python package. "
- "Please install it with `pip install ctranslate2`."
- )
-
- try:
- import transformers
- except ImportError:
- raise ImportError(
- "Could not import transformers python package. "
- "Please install it with `pip install transformers`."
- )
-
- values["client"] = ctranslate2.Generator(
- model_path=values["model_path"],
- device=values["device"],
- device_index=values["device_index"],
- compute_type=values["compute_type"],
- **values["ctranslate2_kwargs"],
- )
-
- values["tokenizer"] = transformers.AutoTokenizer.from_pretrained(
- values["tokenizer_name"]
- )
-
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters."""
- return {
- "max_length": self.max_length,
- "sampling_topk": self.sampling_topk,
- "sampling_topp": self.sampling_topp,
- "sampling_temperature": self.sampling_temperature,
- }
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- # build sampling parameters
- params = {**self._default_params, **kwargs}
-
- # call the model
- encoded_prompts = self.tokenizer(prompts)["input_ids"]
- tokenized_prompts = [
- self.tokenizer.convert_ids_to_tokens(encoded_prompt)
- for encoded_prompt in encoded_prompts
- ]
-
- results = self.client.generate_batch(tokenized_prompts, **params)
-
- sequences = [result.sequences_ids[0] for result in results]
- decoded_sequences = [self.tokenizer.decode(seq) for seq in sequences]
-
- generations = []
- for text in decoded_sequences:
- generations.append([Generation(text=text)])
-
- return LLMResult(generations=generations)
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "ctranslate2"
diff --git a/commune/modules/model/llm/databricks.py b/commune/modules/model/llm/databricks.py
deleted file mode 100644
index fb4a3674b..000000000
--- a/commune/modules/model/llm/databricks.py
+++ /dev/null
@@ -1,333 +0,0 @@
-import os
-from abc import ABC, abstractmethod
-from typing import Any, Callable, Dict, List, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import (
- BaseModel,
- Extra,
- Field,
- PrivateAttr,
- root_validator,
- validator,
-)
-
-__all__ = ["Databricks"]
-
-
-class _DatabricksClientBase(BaseModel, ABC):
- """A base JSON API client that talks to Databricks."""
-
- api_url: str
- api_token: str
-
- def post_raw(self, request: Any) -> Any:
- headers = {"Authorization": f"Bearer {self.api_token}"}
- response = requests.post(self.api_url, headers=headers, json=request)
- # TODO: error handling and automatic retries
- if not response.ok:
- raise ValueError(f"HTTP {response.status_code} error: {response.text}")
- return response.json()
-
- @abstractmethod
- def post(self, request: Any) -> Any:
- ...
-
-
-class _DatabricksServingEndpointClient(_DatabricksClientBase):
- """An API client that talks to a Databricks serving endpoint."""
-
- host: str
- endpoint_name: str
-
- @root_validator(pre=True)
- def set_api_url(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- if "api_url" not in values:
- host = values["host"]
- endpoint_name = values["endpoint_name"]
- api_url = f"https://{host}/serving-endpoints/{endpoint_name}/invocations"
- values["api_url"] = api_url
- return values
-
- def post(self, request: Any) -> Any:
- # See https://docs.databricks.com/machine-learning/model-serving/score-model-serving-endpoints.html
- wrapped_request = {"dataframe_records": [request]}
- response = self.post_raw(wrapped_request)["predictions"]
- # For a single-record query, the result is not a list.
- if isinstance(response, list):
- response = response[0]
- return response
-
-
-class _DatabricksClusterDriverProxyClient(_DatabricksClientBase):
- """An API client that talks to a Databricks cluster driver proxy app."""
-
- host: str
- cluster_id: str
- cluster_driver_port: str
-
- @root_validator(pre=True)
- def set_api_url(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- if "api_url" not in values:
- host = values["host"]
- cluster_id = values["cluster_id"]
- port = values["cluster_driver_port"]
- api_url = f"https://{host}/driver-proxy-api/o/0/{cluster_id}/{port}"
- values["api_url"] = api_url
- return values
-
- def post(self, request: Any) -> Any:
- return self.post_raw(request)
-
-
-def get_repl_context() -> Any:
- """Gets the notebook REPL context if running inside a Databricks notebook.
- Returns None otherwise.
- """
- try:
- from dbruntime.databricks_repl_context import get_context
-
- return get_context()
- except ImportError:
- raise ValueError(
- "Cannot access dbruntime, not running inside a Databricks notebook."
- )
-
-
-def get_default_host() -> str:
- """Gets the default Databricks workspace hostname.
- Raises an error if the hostname cannot be automatically determined.
- """
- host = os.getenv("DATABRICKS_HOST")
- if not host:
- try:
- host = get_repl_context().browserHostName
- if not host:
- raise ValueError("context doesn't contain browserHostName.")
- except Exception as e:
- raise ValueError(
- "host was not set and cannot be automatically inferred. Set "
- f"environment variable 'DATABRICKS_HOST'. Received error: {e}"
- )
- # TODO: support Databricks CLI profile
- host = host.lstrip("https://").lstrip("http://").rstrip("/")
- return host
-
-
-def get_default_api_token() -> str:
- """Gets the default Databricks personal access token.
- Raises an error if the token cannot be automatically determined.
- """
- if api_token := os.getenv("DATABRICKS_TOKEN"):
- return api_token
- try:
- api_token = get_repl_context().apiToken
- if not api_token:
- raise ValueError("context doesn't contain apiToken.")
- except Exception as e:
- raise ValueError(
- "api_token was not set and cannot be automatically inferred. Set "
- f"environment variable 'DATABRICKS_TOKEN'. Received error: {e}"
- )
- # TODO: support Databricks CLI profile
- return api_token
-
-
-class Databricks(LLM):
- """Databricks serving endpoint or a cluster driver proxy app for LLM.
-
- It supports two endpoint types:
-
- * **Serving endpoint** (recommended for both production and development).
- We assume that an LLM was registered and deployed to a serving endpoint.
- To wrap it as an LLM you must have "Can Query" permission to the endpoint.
- Set ``endpoint_name`` accordingly and do not set ``cluster_id`` and
- ``cluster_driver_port``.
- The expected model signature is:
-
- * inputs::
-
- [{"name": "prompt", "type": "string"},
- {"name": "stop", "type": "list[string]"}]
-
- * outputs: ``[{"type": "string"}]``
-
- * **Cluster driver proxy app** (recommended for interactive development).
- One can load an LLM on a Databricks interactive cluster and start a local HTTP
- server on the driver node to serve the model at ``/`` using HTTP POST method
- with JSON input/output.
- Please use a port number between ``[3000, 8000]`` and let the server listen to
- the driver IP address or simply ``0.0.0.0`` instead of localhost only.
- To wrap it as an LLM you must have "Can Attach To" permission to the cluster.
- Set ``cluster_id`` and ``cluster_driver_port`` and do not set ``endpoint_name``.
- The expected server schema (using JSON schema) is:
-
- * inputs::
-
- {"type": "object",
- "properties": {
- "prompt": {"type": "string"},
- "stop": {"type": "array", "items": {"type": "string"}}},
- "required": ["prompt"]}`
-
- * outputs: ``{"type": "string"}``
-
- If the endpoint model signature is different or you want to set extra params,
- you can use `transform_input_fn` and `transform_output_fn` to apply necessary
- transformations before and after the query.
- """
-
- host: str = Field(default_factory=get_default_host)
- """Databricks workspace hostname.
- If not provided, the default value is determined by
-
- * the ``DATABRICKS_HOST`` environment variable if present, or
- * the hostname of the current Databricks workspace if running inside
- a Databricks notebook attached to an interactive cluster in "single user"
- or "no isolation shared" mode.
- """
-
- api_token: str = Field(default_factory=get_default_api_token)
- """Databricks personal access token.
- If not provided, the default value is determined by
-
- * the ``DATABRICKS_TOKEN`` environment variable if present, or
- * an automatically generated temporary token if running inside a Databricks
- notebook attached to an interactive cluster in "single user" or
- "no isolation shared" mode.
- """
-
- endpoint_name: Optional[str] = None
- """Name of the model serving endpoint.
- You must specify the endpoint name to connect to a model serving endpoint.
- You must not set both ``endpoint_name`` and ``cluster_id``.
- """
-
- cluster_id: Optional[str] = None
- """ID of the cluster if connecting to a cluster driver proxy app.
- If neither ``endpoint_name`` nor ``cluster_id`` is not provided and the code runs
- inside a Databricks notebook attached to an interactive cluster in "single user"
- or "no isolation shared" mode, the current cluster ID is used as default.
- You must not set both ``endpoint_name`` and ``cluster_id``.
- """
-
- cluster_driver_port: Optional[str] = None
- """The port number used by the HTTP server running on the cluster driver node.
- The server should listen on the driver IP address or simply ``0.0.0.0`` to connect.
- We recommend the server using a port number between ``[3000, 8000]``.
- """
-
- model_kwargs: Optional[Dict[str, Any]] = None
- """Extra parameters to pass to the endpoint."""
-
- transform_input_fn: Optional[Callable] = None
- """A function that transforms ``{prompt, stop, **kwargs}`` into a JSON-compatible
- request object that the endpoint accepts.
- For example, you can apply a prompt template to the input prompt.
- """
-
- transform_output_fn: Optional[Callable[..., str]] = None
- """A function that transforms the output from the endpoint to the generated text.
- """
-
- _client: _DatabricksClientBase = PrivateAttr()
-
- class Config:
- extra = Extra.forbid
- underscore_attrs_are_private = True
-
- @validator("cluster_id", always=True)
- def set_cluster_id(cls, v: Any, values: Dict[str, Any]) -> Optional[str]:
- if v and values["endpoint_name"]:
- raise ValueError("Cannot set both endpoint_name and cluster_id.")
- elif values["endpoint_name"]:
- return None
- elif v:
- return v
- else:
- try:
- if v := get_repl_context().clusterId:
- return v
- raise ValueError("Context doesn't contain clusterId.")
- except Exception as e:
- raise ValueError(
- "Neither endpoint_name nor cluster_id was set. "
- "And the cluster_id cannot be automatically determined. Received"
- f" error: {e}"
- )
-
- @validator("cluster_driver_port", always=True)
- def set_cluster_driver_port(cls, v: Any, values: Dict[str, Any]) -> Optional[str]:
- if v and values["endpoint_name"]:
- raise ValueError("Cannot set both endpoint_name and cluster_driver_port.")
- elif values["endpoint_name"]:
- return None
- elif v is None:
- raise ValueError(
- "Must set cluster_driver_port to connect to a cluster driver."
- )
- elif int(v) <= 0:
- raise ValueError(f"Invalid cluster_driver_port: {v}")
- else:
- return v
-
- @validator("model_kwargs", always=True)
- def set_model_kwargs(cls, v: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
- if v:
- assert "prompt" not in v, "model_kwargs must not contain key 'prompt'"
- assert "stop" not in v, "model_kwargs must not contain key 'stop'"
- return v
-
- def __init__(self, **data: Any):
- super().__init__(**data)
- if self.endpoint_name:
- self._client = _DatabricksServingEndpointClient(
- host=self.host,
- api_token=self.api_token,
- endpoint_name=self.endpoint_name,
- )
- elif self.cluster_id and self.cluster_driver_port:
- self._client = _DatabricksClusterDriverProxyClient(
- host=self.host,
- api_token=self.api_token,
- cluster_id=self.cluster_id,
- cluster_driver_port=self.cluster_driver_port,
- )
- else:
- raise ValueError(
- "Must specify either endpoint_name or cluster_id/cluster_driver_port."
- )
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "databricks"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Queries the LLM endpoint with the given prompt and stop sequence."""
-
- # TODO: support callbacks
-
- request = {"prompt": prompt, "stop": stop}
- request.update(kwargs)
- if self.model_kwargs:
- request.update(self.model_kwargs)
-
- if self.transform_input_fn:
- request = self.transform_input_fn(**request)
-
- response = self._client.post(request)
-
- if self.transform_output_fn:
- response = self.transform_output_fn(response)
-
- return response
diff --git a/commune/modules/model/llm/deepinfra.py b/commune/modules/model/llm/deepinfra.py
deleted file mode 100644
index 9229d2712..000000000
--- a/commune/modules/model/llm/deepinfra.py
+++ /dev/null
@@ -1,118 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-DEFAULT_MODEL_ID = "google/flan-t5-xl"
-
-
-class DeepInfra(LLM):
- """DeepInfra models.
-
- To use, you should have the ``requests`` python package installed, and the
- environment variable ``DEEPINFRA_API_TOKEN`` set with your API token, or pass
- it as a named parameter to the constructor.
-
- Only supports `text-generation` and `text2text-generation` for now.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import DeepInfra
- di = DeepInfra(model_id="google/flan-t5-xl",
- deepinfra_api_token="my-api-key")
- """
-
- model_id: str = DEFAULT_MODEL_ID
- model_kwargs: Optional[dict] = None
-
- deepinfra_api_token: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- deepinfra_api_token = get_from_dict_or_env(
- values, "deepinfra_api_token", "DEEPINFRA_API_TOKEN"
- )
- values["deepinfra_api_token"] = deepinfra_api_token
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_id": self.model_id},
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "deepinfra"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to DeepInfra's inference API endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = di("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
- _model_kwargs = {**_model_kwargs, **kwargs}
- # HTTP headers for authorization
- headers = {
- "Authorization": f"bearer {self.deepinfra_api_token}",
- "Content-Type": "application/json",
- }
-
- try:
- res = requests.post(
- f"https://api.deepinfra.com/v1/inference/{self.model_id}",
- headers=headers,
- json={"input": prompt, **_model_kwargs},
- )
- except requests.exceptions.RequestException as e:
- raise ValueError(f"Error raised by inference endpoint: {e}")
-
- if res.status_code != 200:
- raise ValueError(
- "Error raised by inference API HTTP code: %s, %s"
- % (res.status_code, res.text)
- )
- try:
- t = res.json()
- text = t["results"][0]["generated_text"]
- except requests.exceptions.JSONDecodeError as e:
- raise ValueError(
- f"Error raised by inference API: {e}.\nResponse: {res.text}"
- )
-
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/deepsparse.py b/commune/modules/model/llm/deepsparse.py
deleted file mode 100644
index ccb753bf6..000000000
--- a/commune/modules/model/llm/deepsparse.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# flake8: noqa
-from typing import Any, Dict, Optional, List
-
-from langchain.pydantic_v1 import root_validator
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-
-
-class DeepSparse(LLM):
- """Neural Magic DeepSparse LLM interface.
-
- To use, you should have the ``deepsparse`` or ``deepsparse-nightly``
- python package installed. See https://github.com/neuralmagic/deepsparse
-
- This interface let's you deploy optimized LLMs straight from the
- [SparseZoo](https://sparsezoo.neuralmagic.com/?useCase=text_generation)
- Example:
- .. code-block:: python
- from langchain.llms import DeepSparse
- llm = DeepSparse(model="zoo:nlg/text_generation/codegen_mono-350m/pytorch/huggingface/bigpython_bigquery_thepile/base-none")
- """ # noqa: E501
-
- pipeline: Any #: :meta private:
-
- model: str
- """The path to a model file or directory or the name of a SparseZoo model stub."""
-
- config: Optional[Dict[str, Any]] = None
- """Key word arguments passed to the pipeline."""
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {
- "model": self.model,
- "config": self.config,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "deepsparse"
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that ``deepsparse`` package is installed."""
- try:
- from deepsparse import Pipeline
- except ImportError:
- raise ImportError(
- "Could not import `deepsparse` package. "
- "Please install it with `pip install deepsparse`"
- )
-
- config = values["config"] or {}
-
- values["pipeline"] = Pipeline.create(
- task="text_generation",
- model_path=values["model"],
- **config,
- )
- return values
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Generate text from a prompt.
- Args:
- prompt: The prompt to generate text from.
- stop: A list of strings to stop generation when encountered.
- Returns:
- The generated text.
- Example:
- .. code-block:: python
- response = llm("Tell me a joke.")
- """
- text = self.pipeline(sequences=prompt).sequences[0]
-
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return "".join(text)
diff --git a/commune/modules/model/llm/edenai.py b/commune/modules/model/llm/edenai.py
deleted file mode 100644
index 521653b42..000000000
--- a/commune/modules/model/llm/edenai.py
+++ /dev/null
@@ -1,265 +0,0 @@
-"""Wrapper around EdenAI's Generation API."""
-import logging
-from typing import Any, Dict, List, Literal, Optional
-
-from aiohttp import ClientSession
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.requests import Requests
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class EdenAI(LLM):
- """Wrapper around edenai models.
-
- To use, you should have
- the environment variable ``EDENAI_API_KEY`` set with your API token.
- You can find your token here: https://app.edenai.run/admin/account/settings
-
- `feature` and `subfeature` are required, but any other model parameters can also be
- passed in with the format params={model_param: value, ...}
-
- for api reference check edenai documentation: http://docs.edenai.co.
- """
-
- base_url: str = "https://api.edenai.run/v2"
-
- edenai_api_key: Optional[str] = None
-
- feature: Literal["text", "image"] = "text"
- """Which generative feature to use, use text by default"""
-
- subfeature: Literal["generation"] = "generation"
- """Subfeature of above feature, use generation by default"""
-
- provider: str
- """Generative provider to use (eg: openai,stabilityai,cohere,google etc.)"""
-
- model: Optional[str] = None
- """
- model name for above provider (eg: 'text-davinci-003' for openai)
- available models are shown on https://docs.edenai.co/ under 'available providers'
- """
-
- # Optional parameters to add depending of chosen feature
- # see api reference for more infos
- temperature: Optional[float] = Field(default=None, ge=0, le=1) # for text
- max_tokens: Optional[int] = Field(default=None, ge=0) # for text
- resolution: Optional[Literal["256x256", "512x512", "1024x1024"]] = None # for image
-
- params: Dict[str, Any] = Field(default_factory=dict)
- """
- DEPRECATED: use temperature, max_tokens, resolution directly
- optional parameters to pass to api
- """
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """extra parameters"""
-
- stop_sequences: Optional[List[str]] = None
- """Stop sequences to use."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key exists in environment."""
- values["edenai_api_key"] = get_from_dict_or_env(
- values, "edenai_api_key", "EDENAI_API_KEY"
- )
- return values
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @property
- def _llm_type(self) -> str:
- """Return type of model."""
- return "edenai"
-
- def _format_output(self, output: dict) -> str:
- if self.feature == "text":
- return output[self.provider]["generated_text"]
- else:
- return output[self.provider]["items"][0]["image"]
-
- @staticmethod
- def get_user_agent() -> str:
- from langchain import __version__
-
- return f"langchain/{__version__}"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to EdenAI's text generation endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
-
- Returns:
- json formatted str response.
- """
- stops = None
- if self.stop_sequences is not None and stop is not None:
- raise ValueError(
- "stop sequences found in both the input and default params."
- )
- elif self.stop_sequences is not None:
- stops = self.stop_sequences
- else:
- stops = stop
-
- url = f"{self.base_url}/{self.feature}/{self.subfeature}"
- headers = {
- "Authorization": f"Bearer {self.edenai_api_key}",
- "User-Agent": self.get_user_agent(),
- }
- payload: Dict[str, Any] = {
- "providers": self.provider,
- "text": prompt,
- "max_tokens": self.max_tokens,
- "temperature": self.temperature,
- "resolution": self.resolution,
- **self.params,
- **kwargs,
- "num_images": 1, # always limit to 1 (ignored for text)
- }
-
- # filter None values to not pass them to the http payload
- payload = {k: v for k, v in payload.items() if v is not None}
-
- if self.model is not None:
- payload["settings"] = {self.provider: self.model}
-
- request = Requests(headers=headers)
- response = request.post(url=url, data=payload)
-
- if response.status_code >= 500:
- raise Exception(f"EdenAI Server: Error {response.status_code}")
- elif response.status_code >= 400:
- raise ValueError(f"EdenAI received an invalid payload: {response.text}")
- elif response.status_code != 200:
- raise Exception(
- f"EdenAI returned an unexpected response with status "
- f"{response.status_code}: {response.text}"
- )
-
- data = response.json()
- provider_response = data[self.provider]
- if provider_response.get("status") == "fail":
- err_msg = provider_response.get("error", {}).get("message")
- raise Exception(err_msg)
-
- output = self._format_output(data)
-
- if stops is not None:
- output = enforce_stop_tokens(output, stops)
-
- return output
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call EdenAi model to get predictions based on the prompt.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: A list of stop words (optional).
- run_manager: A callback manager for async interaction with LLMs.
-
- Returns:
- The string generated by the model.
- """
-
- stops = None
- if self.stop_sequences is not None and stop is not None:
- raise ValueError(
- "stop sequences found in both the input and default params."
- )
- elif self.stop_sequences is not None:
- stops = self.stop_sequences
- else:
- stops = stop
-
- url = f"{self.base_url}/{self.feature}/{self.subfeature}"
- headers = {
- "Authorization": f"Bearer {self.edenai_api_key}",
- "User-Agent": self.get_user_agent(),
- }
- payload: Dict[str, Any] = {
- "providers": self.provider,
- "text": prompt,
- "max_tokens": self.max_tokens,
- "temperature": self.temperature,
- "resolution": self.resolution,
- **self.params,
- **kwargs,
- "num_images": 1, # always limit to 1 (ignored for text)
- }
-
- # filter `None` values to not pass them to the http payload as null
- payload = {k: v for k, v in payload.items() if v is not None}
-
- if self.model is not None:
- payload["settings"] = {self.provider: self.model}
-
- async with ClientSession() as session:
- async with session.post(url, json=payload, headers=headers) as response:
- if response.status >= 500:
- raise Exception(f"EdenAI Server: Error {response.status}")
- elif response.status >= 400:
- raise ValueError(
- f"EdenAI received an invalid payload: {response.text}"
- )
- elif response.status != 200:
- raise Exception(
- f"EdenAI returned an unexpected response with status "
- f"{response.status}: {response.text}"
- )
-
- response_json = await response.json()
- provider_response = response_json[self.provider]
- if provider_response.get("status") == "fail":
- err_msg = provider_response.get("error", {}).get("message")
- raise Exception(err_msg)
-
- output = self._format_output(response_json)
- if stops is not None:
- output = enforce_stop_tokens(output, stops)
-
- return output
diff --git a/commune/modules/model/llm/fake.py b/commune/modules/model/llm/fake.py
deleted file mode 100644
index b3c22eb64..000000000
--- a/commune/modules/model/llm/fake.py
+++ /dev/null
@@ -1,90 +0,0 @@
-import asyncio
-import time
-from typing import Any, AsyncIterator, Iterator, List, Mapping, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.schema.language_model import LanguageModelInput
-from langchain.schema.runnable import RunnableConfig
-
-
-class FakeListLLM(LLM):
- """Fake LLM for testing purposes."""
-
- responses: List
- sleep: Optional[float] = None
- i: int = 0
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "fake-list"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Return next response"""
- response = self.responses[self.i]
- if self.i < len(self.responses) - 1:
- self.i += 1
- else:
- self.i = 0
- return response
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Return next response"""
- response = self.responses[self.i]
- if self.i < len(self.responses) - 1:
- self.i += 1
- else:
- self.i = 0
- return response
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- return {"responses": self.responses}
-
-
-class FakeStreamingListLLM(FakeListLLM):
- """Fake streaming list LLM for testing purposes."""
-
- def stream(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> Iterator[str]:
- result = self.invoke(input, config)
- for c in result:
- if self.sleep is not None:
- time.sleep(self.sleep)
- yield c
-
- async def astream(
- self,
- input: LanguageModelInput,
- config: Optional[RunnableConfig] = None,
- *,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> AsyncIterator[str]:
- result = await self.ainvoke(input, config)
- for c in result:
- if self.sleep is not None:
- await asyncio.sleep(self.sleep)
- yield c
diff --git a/commune/modules/model/llm/fireworks.py b/commune/modules/model/llm/fireworks.py
deleted file mode 100644
index 2b4b5f0ff..000000000
--- a/commune/modules/model/llm/fireworks.py
+++ /dev/null
@@ -1,377 +0,0 @@
-"""Wrapper around Fireworks APIs"""
-import json
-import logging
-from typing import (
- Any,
- Dict,
- List,
- Optional,
- Set,
- Tuple,
- Union,
-)
-
-import requests
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import BaseLLM
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import Generation, LLMResult
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class BaseFireworks(BaseLLM):
- """Wrapper around Fireworks large language models."""
-
- model_id: str = Field("accounts/fireworks/models/llama-v2-7b-chat", alias="model")
- """Model name to use."""
- temperature: float = 0.7
- """What sampling temperature to use."""
- max_tokens: int = 512
- """The maximum number of tokens to generate in the completion.
- -1 returns as many tokens as possible given the prompt and
- the models maximal context size."""
- top_p: float = 1
- """Total probability mass of tokens to consider at each step."""
- fireworks_api_key: Optional[str] = None
- """Api key to use fireworks API"""
- batch_size: int = 20
- """Batch size to use when passing multiple documents to generate."""
- request_timeout: Optional[Union[float, Tuple[float, float]]] = None
- """Timeout for requests to Fireworks completion API. Default is 600 seconds."""
- max_retries: int = 6
- """Maximum number of retries to make when generating."""
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"fireworks_api_key": "FIREWORKS_API_KEY"}
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- def __new__(cls, **data: Any) -> Any:
- """Initialize the Fireworks object."""
- data.get("model_id", "")
- return super().__new__(cls)
-
- class Config:
- """Configuration for this pydantic object."""
-
- allow_population_by_field_name = True
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["fireworks_api_key"] = get_from_dict_or_env(
- values, "fireworks_api_key", "FIREWORKS_API_KEY"
- )
- return values
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call out to Fireworks endpoint with k unique prompts.
- Args:
- prompts: The prompts to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- The full LLM output.
- """
- params = {"model": self.model_id}
- params = {**params, **kwargs}
- sub_prompts = self.get_batch_prompts(params, prompts, stop)
- choices = []
- token_usage: Dict[str, int] = {}
- _keys = {"completion_tokens", "prompt_tokens", "total_tokens"}
- for _prompts in sub_prompts:
- response = completion_with_retry(self, prompt=prompts, **params)
- choices.extend(response)
- update_token_usage(_keys, response, token_usage)
-
- return self.create_llm_result(choices, prompts, token_usage)
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call out to Fireworks endpoint async with k unique prompts."""
- params = {"model": self.model_id}
- params = {**params, **kwargs}
- sub_prompts = self.get_batch_prompts(params, prompts, stop)
- choices = []
- token_usage: Dict[str, int] = {}
- _keys = {"completion_tokens", "prompt_tokens", "total_tokens"}
- for _prompts in sub_prompts:
- response = await acompletion_with_retry(self, prompt=_prompts, **params)
- choices.extend(response)
- update_token_usage(_keys, response, token_usage)
-
- return self.create_llm_result(choices, prompts, token_usage)
-
- def get_batch_prompts(
- self,
- params: Dict[str, Any],
- prompts: List[str],
- stop: Optional[List[str]] = None,
- ) -> List[List[str]]:
- """Get the sub prompts for llm call."""
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
-
- sub_prompts = [
- prompts[i : i + self.batch_size]
- for i in range(0, len(prompts), self.batch_size)
- ]
- return sub_prompts
-
- def create_llm_result(
- self, choices: Any, prompts: List[str], token_usage: Dict[str, int]
- ) -> LLMResult:
- """Create the LLMResult from the choices and prompts."""
- generations = []
-
- for i, _ in enumerate(prompts):
- sub_choices = choices[i : (i + 1)]
- generations.append(
- [
- Generation(
- text=choice,
- )
- for choice in sub_choices
- ]
- )
- llm_output = {"token_usage": token_usage, "model_id": self.model_id}
- return LLMResult(generations=generations, llm_output=llm_output)
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "fireworks"
-
-
-class FireworksChat(BaseLLM):
- """Wrapper around Fireworks Chat large language models.
- To use, you should have the ``fireworksai`` python package installed, and the
- environment variable ``FIREWORKS_API_KEY`` set with your API key.
- Any parameters that are valid to be passed to the fireworks.create
- call can be passed in, even if not explicitly saved on this class.
- Example:
- .. code-block:: python
- from langchain.llms import FireworksChat
- fireworkschat = FireworksChat(model_id=""llama-v2-13b-chat"")
- """
-
- model_id: str = "accounts/fireworks/models/llama-v2-7b-chat"
- """Model name to use."""
- temperature: float = 0.7
- """What sampling temperature to use."""
- max_tokens: int = 512
- """The maximum number of tokens to generate in the completion.
- -1 returns as many tokens as possible given the prompt and
- the models maximal context size."""
- top_p: float = 1
- """Total probability mass of tokens to consider at each step."""
- fireworks_api_key: Optional[str] = None
- max_retries: int = 6
- request_timeout: Optional[Union[float, Tuple[float, float]]] = None
- """Timeout for requests to Fireworks completion API. Default is 600 seconds."""
- """Maximum number of retries to make when generating."""
- prefix_messages: List = Field(default_factory=list)
- """Series of messages for Chat input."""
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment"""
- values["fireworks_api_key"] = get_from_dict_or_env(
- values, "fireworks_api_key", "FIREWORKS_API_KEY"
- )
- return values
-
- def _get_chat_params(
- self, prompts: List[str], stop: Optional[List[str]] = None
- ) -> Tuple:
- if len(prompts) > 1:
- raise ValueError(
- f"FireworksChat currently only supports single prompt, got {prompts}"
- )
- messages = self.prefix_messages + [{"role": "user", "content": prompts[0]}]
- params: Dict[str, Any] = {**{"model": self.model_id}}
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
-
- return messages, params
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- messages, params = self._get_chat_params(prompts, stop)
- params = {**params, **kwargs}
- full_response = completion_with_retry(self, messages=messages, **params)
- llm_output = {
- "model_id": self.model_id,
- }
- return LLMResult(
- generations=[[Generation(text=full_response[0])]],
- llm_output=llm_output,
- )
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- messages, params = self._get_chat_params(prompts, stop)
- params = {**params, **kwargs}
- full_response = await acompletion_with_retry(self, messages=messages, **params)
- llm_output = {
- "model_id": self.model_id,
- }
- return LLMResult(
- generations=[[Generation(text=full_response[0])]],
- llm_output=llm_output,
- )
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "fireworks-chat"
-
-
-class Fireworks(BaseFireworks):
- """Wrapper around Fireworks large language models.
- To use, you should have the ``fireworks`` python package installed, and the
- environment variable ``FIREWORKS_API_KEY`` set with your API key.
- Any parameters that are valid to be passed to the fireworks.create
- call can be passed in, even if not explicitly saved on this class.
- Example:
- .. code-block:: python
- from langchain.llms import fireworks
- llm = Fireworks(model_id="llama-v2-13b")
- """
-
-
-def update_token_usage(
- keys: Set[str], response: Dict[str, Any], token_usage: Dict[str, Any]
-) -> None:
- """Update token usage."""
- _keys_to_use = keys.intersection(response)
- for _key in _keys_to_use:
- if _key not in token_usage:
- token_usage[_key] = response["usage"][_key]
- else:
- token_usage[_key] += response["usage"][_key]
-
-
-def execute(
- prompt: str,
- model: str,
- api_key: Optional[str],
- max_tokens: int = 256,
- temperature: float = 0.0,
- top_p: float = 1.0,
-) -> Any:
- """Execute LLM query"""
- requestUrl = "https://api.fireworks.ai/inference/v1/completions"
- requestBody = {
- "model": model,
- "prompt": prompt,
- "max_tokens": max_tokens,
- "temperature": temperature,
- "top_p": top_p,
- }
- requestHeaders = {
- "Authorization": f"Bearer {api_key}",
- "Accept": "application/json",
- "Content-Type": "application/json",
- }
- response = requests.post(requestUrl, headers=requestHeaders, json=requestBody)
- return response.text
-
-
-def completion_with_retry(
- llm: Union[BaseFireworks, FireworksChat], **kwargs: Any
-) -> Any:
- """Use tenacity to retry the completion call."""
- if "prompt" not in kwargs.keys():
- answers = []
- for i in range(len(kwargs["messages"])):
- result = kwargs["messages"][i]["content"]
- result = execute(
- result,
- kwargs["model"],
- llm.fireworks_api_key,
- llm.max_tokens,
- llm.temperature,
- llm.top_p,
- )
- curr_string = json.loads(result)["choices"][0]["text"]
- answers.append(curr_string)
- else:
- answers = []
- for i in range(len(kwargs["prompt"])):
- result = kwargs["prompt"][i]
- result = execute(
- result,
- kwargs["model"],
- llm.fireworks_api_key,
- llm.max_tokens,
- llm.temperature,
- llm.top_p,
- )
- curr_string = json.loads(result)["choices"][0]["text"]
- answers.append(curr_string)
- return answers
-
-
-async def acompletion_with_retry(
- llm: Union[BaseFireworks, FireworksChat], **kwargs: Any
-) -> Any:
- """Use tenacity to retry the async completion call."""
- if "prompt" not in kwargs.keys():
- answers = []
- for i in range(len(kwargs["messages"])):
- result = kwargs["messages"][i]["content"]
- result = execute(
- result,
- kwargs["model"],
- llm.fireworks_api_key,
- llm.max_tokens,
- llm.temperature,
- )
- curr_string = json.loads(result)["choices"][0]["text"]
- answers.append(curr_string)
- else:
- answers = []
- for i in range(len(kwargs["prompt"])):
- result = kwargs["prompt"][i]
- result = execute(
- result,
- kwargs["model"],
- llm.fireworks_api_key,
- llm.max_tokens,
- llm.temperature,
- )
- curr_string = json.loads(result)["choices"][0]["text"]
- answers.append(curr_string)
- return answers
diff --git a/commune/modules/model/llm/forefrontai.py b/commune/modules/model/llm/forefrontai.py
deleted file mode 100644
index 7d82b6896..000000000
--- a/commune/modules/model/llm/forefrontai.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class ForefrontAI(LLM):
- """ForefrontAI large language models.
-
- To use, you should have the environment variable ``FOREFRONTAI_API_KEY``
- set with your API key.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import ForefrontAI
- forefrontai = ForefrontAI(endpoint_url="")
- """
-
- endpoint_url: str = ""
- """Model name to use."""
-
- temperature: float = 0.7
- """What sampling temperature to use."""
-
- length: int = 256
- """The maximum number of tokens to generate in the completion."""
-
- top_p: float = 1.0
- """Total probability mass of tokens to consider at each step."""
-
- top_k: int = 40
- """The number of highest probability vocabulary tokens to
- keep for top-k-filtering."""
-
- repetition_penalty: int = 1
- """Penalizes repeated tokens according to frequency."""
-
- forefrontai_api_key: Optional[str] = None
-
- base_url: Optional[str] = None
- """Base url to use, if None decides based on model name."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key exists in environment."""
- forefrontai_api_key = get_from_dict_or_env(
- values, "forefrontai_api_key", "FOREFRONTAI_API_KEY"
- )
- values["forefrontai_api_key"] = forefrontai_api_key
- return values
-
- @property
- def _default_params(self) -> Mapping[str, Any]:
- """Get the default parameters for calling ForefrontAI API."""
- return {
- "temperature": self.temperature,
- "length": self.length,
- "top_p": self.top_p,
- "top_k": self.top_k,
- "repetition_penalty": self.repetition_penalty,
- }
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{"endpoint_url": self.endpoint_url}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "forefrontai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to ForefrontAI's complete endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = ForefrontAI("Tell me a joke.")
- """
- response = requests.post(
- url=self.endpoint_url,
- headers={
- "Authorization": f"Bearer {self.forefrontai_api_key}",
- "Content-Type": "application/json",
- },
- json={"text": prompt, **self._default_params, **kwargs},
- )
- response_json = response.json()
- text = response_json["result"][0]["completion"]
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/google_palm.py b/commune/modules/model/llm/google_palm.py
deleted file mode 100644
index 1a0a40997..000000000
--- a/commune/modules/model/llm/google_palm.py
+++ /dev/null
@@ -1,164 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import Any, Callable, Dict, List, Optional
-
-from tenacity import (
- before_sleep_log,
- retry,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms import BaseLLM
-from langchain.pydantic_v1 import BaseModel, root_validator
-from langchain.schema import Generation, LLMResult
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-def _create_retry_decorator() -> Callable[[Any], Any]:
- """Returns a tenacity retry decorator, preconfigured to handle PaLM exceptions"""
- try:
- import google.api_core.exceptions
- except ImportError:
- raise ImportError(
- "Could not import google-api-core python package. "
- "Please install it with `pip install google-api-core`."
- )
-
- multiplier = 2
- min_seconds = 1
- max_seconds = 60
- max_retries = 10
-
- return retry(
- reraise=True,
- stop=stop_after_attempt(max_retries),
- wait=wait_exponential(multiplier=multiplier, min=min_seconds, max=max_seconds),
- retry=(
- retry_if_exception_type(google.api_core.exceptions.ResourceExhausted)
- | retry_if_exception_type(google.api_core.exceptions.ServiceUnavailable)
- | retry_if_exception_type(google.api_core.exceptions.GoogleAPIError)
- ),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
-
-def generate_with_retry(llm: GooglePalm, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator()
-
- @retry_decorator
- def _generate_with_retry(**kwargs: Any) -> Any:
- return llm.client.generate_text(**kwargs)
-
- return _generate_with_retry(**kwargs)
-
-
-def _strip_erroneous_leading_spaces(text: str) -> str:
- """Strip erroneous leading spaces from text.
-
- The PaLM API will sometimes erroneously return a single leading space in all
- lines > 1. This function strips that space.
- """
- has_leading_space = all(not line or line[0] == " " for line in text.split("\n")[1:])
- if has_leading_space:
- return text.replace("\n ", "\n")
- else:
- return text
-
-
-class GooglePalm(BaseLLM, BaseModel):
- """Google PaLM models."""
-
- client: Any #: :meta private:
- google_api_key: Optional[str]
- model_name: str = "models/text-bison-001"
- """Model name to use."""
- temperature: float = 0.7
- """Run inference with this temperature. Must by in the closed interval
- [0.0, 1.0]."""
- top_p: Optional[float] = None
- """Decode using nucleus sampling: consider the smallest set of tokens whose
- probability sum is at least top_p. Must be in the closed interval [0.0, 1.0]."""
- top_k: Optional[int] = None
- """Decode using top-k sampling: consider the set of top_k most probable tokens.
- Must be positive."""
- max_output_tokens: Optional[int] = None
- """Maximum number of tokens to include in a candidate. Must be greater than zero.
- If unset, will default to 64."""
- n: int = 1
- """Number of chat completions to generate for each prompt. Note that the API may
- not return the full n completions if duplicates are generated."""
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate api key, python package exists."""
- google_api_key = get_from_dict_or_env(
- values, "google_api_key", "GOOGLE_API_KEY"
- )
- try:
- import google.generativeai as genai
-
- genai.configure(api_key=google_api_key)
- except ImportError:
- raise ImportError(
- "Could not import google-generativeai python package. "
- "Please install it with `pip install google-generativeai`."
- )
-
- values["client"] = genai
-
- if values["temperature"] is not None and not 0 <= values["temperature"] <= 1:
- raise ValueError("temperature must be in the range [0.0, 1.0]")
-
- if values["top_p"] is not None and not 0 <= values["top_p"] <= 1:
- raise ValueError("top_p must be in the range [0.0, 1.0]")
-
- if values["top_k"] is not None and values["top_k"] <= 0:
- raise ValueError("top_k must be positive")
-
- if values["max_output_tokens"] is not None and values["max_output_tokens"] <= 0:
- raise ValueError("max_output_tokens must be greater than zero")
-
- return values
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- generations = []
- for prompt in prompts:
- completion = generate_with_retry(
- self,
- model=self.model_name,
- prompt=prompt,
- stop_sequences=stop,
- temperature=self.temperature,
- top_p=self.top_p,
- top_k=self.top_k,
- max_output_tokens=self.max_output_tokens,
- candidate_count=self.n,
- **kwargs,
- )
-
- prompt_generations = []
- for candidate in completion.candidates:
- raw_text = candidate["output"]
- stripped_text = _strip_erroneous_leading_spaces(raw_text)
- prompt_generations.append(Generation(text=stripped_text))
- generations.append(prompt_generations)
-
- return LLMResult(generations=generations)
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "google_palm"
diff --git a/commune/modules/model/llm/gooseai.py b/commune/modules/model/llm/gooseai.py
deleted file mode 100644
index 831cff9a5..000000000
--- a/commune/modules/model/llm/gooseai.py
+++ /dev/null
@@ -1,151 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class GooseAI(LLM):
- """GooseAI large language models.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``GOOSEAI_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import GooseAI
- gooseai = GooseAI(model_name="gpt-neo-20b")
-
- """
-
- client: Any
-
- model_name: str = "gpt-neo-20b"
- """Model name to use"""
-
- temperature: float = 0.7
- """What sampling temperature to use"""
-
- max_tokens: int = 256
- """The maximum number of tokens to generate in the completion.
- -1 returns as many tokens as possible given the prompt and
- the models maximal context size."""
-
- top_p: float = 1
- """Total probability mass of tokens to consider at each step."""
-
- min_tokens: int = 1
- """The minimum number of tokens to generate in the completion."""
-
- frequency_penalty: float = 0
- """Penalizes repeated tokens according to frequency."""
-
- presence_penalty: float = 0
- """Penalizes repeated tokens."""
-
- n: int = 1
- """How many completions to generate for each prompt."""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not explicitly specified."""
-
- logit_bias: Optional[Dict[str, float]] = Field(default_factory=dict)
- """Adjust the probability of specific tokens being generated."""
-
- gooseai_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.ignore
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""WARNING! {field_name} is not default parameter.
- {field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- gooseai_api_key = get_from_dict_or_env(
- values, "gooseai_api_key", "GOOSEAI_API_KEY"
- )
- try:
- import openai
-
- openai.api_key = gooseai_api_key
- openai.api_base = "https://api.goose.ai/v1"
- values["client"] = openai.Completion
- except ImportError:
- raise ImportError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`."
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling GooseAI API."""
- normal_params = {
- "temperature": self.temperature,
- "max_tokens": self.max_tokens,
- "top_p": self.top_p,
- "min_tokens": self.min_tokens,
- "frequency_penalty": self.frequency_penalty,
- "presence_penalty": self.presence_penalty,
- "n": self.n,
- "logit_bias": self.logit_bias,
- }
- return {**normal_params, **self.model_kwargs}
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_name": self.model_name}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "gooseai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the GooseAI API."""
- params = self._default_params
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
- params["stop"] = stop
-
- params = {**params, **kwargs}
-
- response = self.client.create(engine=self.model_name, prompt=prompt, **params)
- text = response.choices[0].text
- return text
diff --git a/commune/modules/model/llm/gpt4all.py b/commune/modules/model/llm/gpt4all.py
deleted file mode 100644
index 67aa6d49a..000000000
--- a/commune/modules/model/llm/gpt4all.py
+++ /dev/null
@@ -1,206 +0,0 @@
-from functools import partial
-from typing import Any, Dict, List, Mapping, Optional, Set
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-
-
-class GPT4All(LLM):
- """GPT4All language models.
-
- To use, you should have the ``gpt4all`` python package installed, the
- pre-trained model file, and the model's config information.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import GPT4All
- model = GPT4All(model="./models/gpt4all-model.bin", n_threads=8)
-
- # Simplest invocation
- response = model("Once upon a time, ")
- """
-
- model: str
- """Path to the pre-trained GPT4All model file."""
-
- backend: Optional[str] = Field(None, alias="backend")
-
- max_tokens: int = Field(200, alias="max_tokens")
- """Token context window."""
-
- n_parts: int = Field(-1, alias="n_parts")
- """Number of parts to split the model into.
- If -1, the number of parts is automatically determined."""
-
- seed: int = Field(0, alias="seed")
- """Seed. If -1, a random seed is used."""
-
- f16_kv: bool = Field(False, alias="f16_kv")
- """Use half-precision for key/value cache."""
-
- logits_all: bool = Field(False, alias="logits_all")
- """Return logits for all tokens, not just the last token."""
-
- vocab_only: bool = Field(False, alias="vocab_only")
- """Only load the vocabulary, no weights."""
-
- use_mlock: bool = Field(False, alias="use_mlock")
- """Force system to keep model in RAM."""
-
- embedding: bool = Field(False, alias="embedding")
- """Use embedding mode only."""
-
- n_threads: Optional[int] = Field(4, alias="n_threads")
- """Number of threads to use."""
-
- n_predict: Optional[int] = 256
- """The maximum number of tokens to generate."""
-
- temp: Optional[float] = 0.7
- """The temperature to use for sampling."""
-
- top_p: Optional[float] = 0.1
- """The top-p value to use for sampling."""
-
- top_k: Optional[int] = 40
- """The top-k value to use for sampling."""
-
- echo: Optional[bool] = False
- """Whether to echo the prompt."""
-
- stop: Optional[List[str]] = []
- """A list of strings to stop generation when encountered."""
-
- repeat_last_n: Optional[int] = 64
- "Last n tokens to penalize"
-
- repeat_penalty: Optional[float] = 1.18
- """The penalty to apply to repeated tokens."""
-
- n_batch: int = Field(8, alias="n_batch")
- """Batch size for prompt processing."""
-
- streaming: bool = False
- """Whether to stream the results or not."""
-
- allow_download: bool = False
- """If model does not exist in ~/.cache/gpt4all/, download it."""
-
- client: Any = None #: :meta private:
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @staticmethod
- def _model_param_names() -> Set[str]:
- return {
- "max_tokens",
- "n_predict",
- "top_k",
- "top_p",
- "temp",
- "n_batch",
- "repeat_penalty",
- "repeat_last_n",
- }
-
- def _default_params(self) -> Dict[str, Any]:
- return {
- "max_tokens": self.max_tokens,
- "n_predict": self.n_predict,
- "top_k": self.top_k,
- "top_p": self.top_p,
- "temp": self.temp,
- "n_batch": self.n_batch,
- "repeat_penalty": self.repeat_penalty,
- "repeat_last_n": self.repeat_last_n,
- }
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that the python package exists in the environment."""
- try:
- from gpt4all import GPT4All as GPT4AllModel
- except ImportError:
- raise ImportError(
- "Could not import gpt4all python package. "
- "Please install it with `pip install gpt4all`."
- )
-
- full_path = values["model"]
- model_path, delimiter, model_name = full_path.rpartition("/")
- model_path += delimiter
-
- values["client"] = GPT4AllModel(
- model_name,
- model_path=model_path or None,
- model_type=values["backend"],
- allow_download=values["allow_download"],
- )
- if values["n_threads"] is not None:
- # set n_threads
- values["client"].model.set_thread_count(values["n_threads"])
-
- try:
- values["backend"] = values["client"].model_type
- except AttributeError:
- # The below is for compatibility with GPT4All Python bindings <= 0.2.3.
- values["backend"] = values["client"].model.model_type
-
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "model": self.model,
- **self._default_params(),
- **{
- k: v for k, v in self.__dict__.items() if k in self._model_param_names()
- },
- }
-
- @property
- def _llm_type(self) -> str:
- """Return the type of llm."""
- return "gpt4all"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- r"""Call out to GPT4All's generate method.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- prompt = "Once upon a time, "
- response = model(prompt, n_predict=55)
- """
- text_callback = None
- if run_manager:
- text_callback = partial(run_manager.on_llm_new_token, verbose=self.verbose)
- text = ""
- params = {**self._default_params(), **kwargs}
- for token in self.client.generate(prompt, **params):
- if text_callback:
- text_callback(token)
- text += token
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/gradient_ai.py b/commune/modules/model/llm/gradient_ai.py
deleted file mode 100644
index 9bc72a8d2..000000000
--- a/commune/modules/model/llm/gradient_ai.py
+++ /dev/null
@@ -1,236 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional, Union
-
-import aiohttp
-import requests
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class GradientLLM(LLM):
- """Gradient.ai LLM Endpoints.
-
- GradientLLM is a class to interact with LLMs on gradient.ai
-
- To use, set the environment variable ``GRADIENT_ACCESS_TOKEN`` with your
- API token and ``GRADIENT_WORKSPACE_ID`` for your gradient workspace,
- or alternatively provide them as keywords to the constructor of this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms.gradientai_endpoint import GradientAIEndpoint
- GradientLLM(
- model_id="cad6644_base_ml_model",
- model_kwargs={
- "max_generated_token_count": 200,
- "temperature": 0.75,
- "top_p": 0.95,
- "top_k": 20,
- "stop": [],
- },
- gradient_workspace_id="12345614fc0_workspace",
- gradient_access_token="gradientai-access_token",
- )
-
- """
-
- model_id: str
- "Underlying gradient.ai model id (base or fine-tuned)."
-
- gradient_workspace_id: Optional[str] = None
- "Underlying gradient.ai workspace_id."
-
- gradient_access_token: Optional[str] = None
- """gradient.ai API Token, which can be generated by going to
- https://auth.gradient.ai/select-workspace
- and selecting "Access tokens" under the profile drop-down.
- """
-
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
-
- gradient_api_url: str = "https://api.gradient.ai/api"
- """Endpoint URL to use."""
-
- aiosession: Optional[aiohttp.ClientSession] = None
- """ClientSession, in case we want to reuse connection for better performance."""
-
- # LLM call kwargs
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator(allow_reuse=True)
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
-
- values["gradient_access_token"] = get_from_dict_or_env(
- values, "gradient_access_token", "GRADIENT_ACCESS_TOKEN"
- )
- values["gradient_workspace_id"] = get_from_dict_or_env(
- values, "gradient_workspace_id", "GRADIENT_WORKSPACE_ID"
- )
-
- if (
- values["gradient_access_token"] is None
- or len(values["gradient_access_token"]) < 10
- ):
- raise ValueError("env variable `GRADIENT_ACCESS_TOKEN` must be set")
-
- if (
- values["gradient_workspace_id"] is None
- or len(values["gradient_access_token"]) < 3
- ):
- raise ValueError("env variable `GRADIENT_WORKSPACE_ID` must be set")
-
- if values["model_kwargs"]:
- kw = values["model_kwargs"]
- if not 0 <= kw.get("temperature", 0.5) <= 1:
- raise ValueError("`temperature` must be in the range [0.0, 1.0]")
-
- if not 0 <= kw.get("top_p", 0.5) <= 1:
- raise ValueError("`top_p` must be in the range [0.0, 1.0]")
-
- if 0 >= kw.get("top_k", 0.5):
- raise ValueError("`top_k` must be positive")
-
- if 0 >= kw.get("max_generated_token_count", 1):
- raise ValueError("`max_generated_token_count` must be positive")
-
- values["gradient_api_url"] = get_from_dict_or_env(
- values, "gradient_api_url", "GRADIENT_API_URL"
- )
-
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"gradient_api_url": self.gradient_api_url},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "gradient"
-
- def _kwargs_post_request(
- self, prompt: str, kwargs: Mapping[str, Any]
- ) -> Mapping[str, Any]:
- """Build the kwargs for the Post request, used by sync
-
- Args:
- prompt (str): prompt used in query
- kwargs (dict): model kwargs in payload
-
- Returns:
- Dict[str, Union[str,dict]]: _description_
- """
- _model_kwargs = self.model_kwargs or {}
- _params = {**_model_kwargs, **kwargs}
-
- return dict(
- url=f"{self.gradient_api_url}/models/{self.model_id}/complete",
- headers={
- "authorization": f"Bearer {self.gradient_access_token}",
- "x-gradient-workspace-id": f"{self.gradient_workspace_id}",
- "accept": "application/json",
- "content-type": "application/json",
- },
- json=dict(
- query=prompt,
- maxGeneratedTokenCount=_params.get("max_generated_token_count", None),
- temperature=_params.get("temperature", None),
- topK=_params.get("top_k", None),
- topP=_params.get("top_p", None),
- ),
- )
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to Gradients API `model/{id}/complete`.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
- """
- try:
- response = requests.post(**self._kwargs_post_request(prompt, kwargs))
- if response.status_code != 200:
- raise Exception(
- f"Gradient returned an unexpected response with status "
- f"{response.status_code}: {response.text}"
- )
- except requests.exceptions.RequestException as e:
- raise Exception(f"RequestException while calling Gradient Endpoint: {e}")
-
- text = response.json()["generatedOutput"]
-
- if stop is not None:
- # Apply stop tokens when making calls to Gradient
- text = enforce_stop_tokens(text, stop)
-
- return text
-
- async def _acall(
- self,
- prompt: str,
- stop: Union[List[str], None] = None,
- run_manager: Union[AsyncCallbackManagerForLLMRun, None] = None,
- **kwargs: Any,
- ) -> str:
- """Async Call to Gradients API `model/{id}/complete`.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
- """
- if not self.aiosession:
- async with aiohttp.ClientSession() as session:
- async with session.post(
- **self._kwargs_post_request(prompt=prompt, kwargs=kwargs)
- ) as response:
- if response.status != 200:
- raise Exception(
- f"Gradient returned an unexpected response with status "
- f"{response.status}: {response.text}"
- )
- text = (await response.json())["generatedOutput"]
- else:
- async with self.aiosession.post(
- **self._kwargs_post_request(prompt=prompt, kwargs=kwargs)
- ) as response:
- if response.status != 200:
- raise Exception(
- f"Gradient returned an unexpected response with status "
- f"{response.status}: {response.text}"
- )
- text = (await response.json())["generatedOutput"]
-
- if stop is not None:
- # Apply stop tokens when making calls to Gradient
- text = enforce_stop_tokens(text, stop)
-
- return text
diff --git a/commune/modules/model/llm/grammars/json.gbnf b/commune/modules/model/llm/grammars/json.gbnf
deleted file mode 100644
index 61bd2b2e6..000000000
--- a/commune/modules/model/llm/grammars/json.gbnf
+++ /dev/null
@@ -1,29 +0,0 @@
-# Grammar for subset of JSON - doesn't support full string or number syntax
-
-root ::= object
-value ::= object | array | string | number | boolean | "null"
-
-object ::=
- "{" ws (
- string ":" ws value
- ("," ws string ":" ws value)*
- )? "}"
-
-array ::=
- "[" ws (
- value
- ("," ws value)*
- )? "]"
-
-string ::=
- "\"" (
- [^"\\] |
- "\\" (["\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]) # escapes
- )* "\"" ws
-
-# Only plain integers currently
-number ::= "-"? [0-9]+ ws
-boolean ::= ("true" | "false") ws
-
-# Optional space: by convention, applied in this grammar after literal chars when allowed
-ws ::= ([ \t\n] ws)?
\ No newline at end of file
diff --git a/commune/modules/model/llm/grammars/list.gbnf b/commune/modules/model/llm/grammars/list.gbnf
deleted file mode 100644
index 30ea6e0c8..000000000
--- a/commune/modules/model/llm/grammars/list.gbnf
+++ /dev/null
@@ -1,14 +0,0 @@
-root ::= "[" items "]" EOF
-
-items ::= item ("," ws* item)*
-
-item ::= string
-
-string ::=
- "\"" word (ws+ word)* "\"" ws*
-
-word ::= [a-zA-Z]+
-
-ws ::= " "
-
-EOF ::= "\n"
\ No newline at end of file
diff --git a/commune/modules/model/llm/huggingface_endpoint.py b/commune/modules/model/llm/huggingface_endpoint.py
deleted file mode 100644
index a1593287a..000000000
--- a/commune/modules/model/llm/huggingface_endpoint.py
+++ /dev/null
@@ -1,156 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-VALID_TASKS = ("text2text-generation", "text-generation", "summarization")
-
-
-class HuggingFaceEndpoint(LLM):
- """HuggingFace Endpoint models.
-
- To use, you should have the ``huggingface_hub`` python package installed, and the
- environment variable ``HUGGINGFACEHUB_API_TOKEN`` set with your API token, or pass
- it as a named parameter to the constructor.
-
- Only supports `text-generation` and `text2text-generation` for now.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import HuggingFaceEndpoint
- endpoint_url = (
- "https://abcdefghijklmnop.us-east-1.aws.endpoints.huggingface.cloud"
- )
- hf = HuggingFaceEndpoint(
- endpoint_url=endpoint_url,
- huggingfacehub_api_token="my-api-key"
- )
- """
-
- endpoint_url: str = ""
- """Endpoint URL to use."""
- task: Optional[str] = None
- """Task to call the model with.
- Should be a task that returns `generated_text` or `summary_text`."""
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
-
- huggingfacehub_api_token: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- huggingfacehub_api_token = get_from_dict_or_env(
- values, "huggingfacehub_api_token", "HUGGINGFACEHUB_API_TOKEN"
- )
- try:
- from huggingface_hub.hf_api import HfApi
-
- try:
- HfApi(
- endpoint="https://huggingface.co", # Can be a Private Hub endpoint.
- token=huggingfacehub_api_token,
- ).whoami()
- except Exception as e:
- raise ValueError(
- "Could not authenticate with huggingface_hub. "
- "Please check your API token."
- ) from e
-
- except ImportError:
- raise ValueError(
- "Could not import huggingface_hub python package. "
- "Please install it with `pip install huggingface_hub`."
- )
- values["huggingfacehub_api_token"] = huggingfacehub_api_token
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"endpoint_url": self.endpoint_url, "task": self.task},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "huggingface_endpoint"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to HuggingFace Hub's inference endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = hf("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
-
- # payload samples
- params = {**_model_kwargs, **kwargs}
- parameter_payload = {"inputs": prompt, "parameters": params}
-
- # HTTP headers for authorization
- headers = {
- "Authorization": f"Bearer {self.huggingfacehub_api_token}",
- "Content-Type": "application/json",
- }
-
- # send request
- try:
- response = requests.post(
- self.endpoint_url, headers=headers, json=parameter_payload
- )
- except requests.exceptions.RequestException as e: # This is the correct syntax
- raise ValueError(f"Error raised by inference endpoint: {e}")
- generated_text = response.json()
- if "error" in generated_text:
- raise ValueError(
- f"Error raised by inference API: {generated_text['error']}"
- )
- if self.task == "text-generation":
- text = generated_text[0]["generated_text"]
- # Remove prompt if included in generated text.
- if text.startswith(prompt):
- text = text[len(prompt) :]
- elif self.task == "text2text-generation":
- text = generated_text[0]["generated_text"]
- elif self.task == "summarization":
- text = generated_text[0]["summary_text"]
- else:
- raise ValueError(
- f"Got invalid task {self.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- if stop is not None:
- # This is a bit hacky, but I can't figure out a better way to enforce
- # stop tokens when making calls to huggingface_hub.
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/huggingface_hub.py b/commune/modules/model/llm/huggingface_hub.py
deleted file mode 100644
index f1bc8977a..000000000
--- a/commune/modules/model/llm/huggingface_hub.py
+++ /dev/null
@@ -1,129 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-DEFAULT_REPO_ID = "gpt2"
-VALID_TASKS = ("text2text-generation", "text-generation", "summarization")
-
-
-class HuggingFaceHub(LLM):
- """HuggingFaceHub models.
-
- To use, you should have the ``huggingface_hub`` python package installed, and the
- environment variable ``HUGGINGFACEHUB_API_TOKEN`` set with your API token, or pass
- it as a named parameter to the constructor.
-
- Only supports `text-generation`, `text2text-generation` and `summarization` for now.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import HuggingFaceHub
- hf = HuggingFaceHub(repo_id="gpt2", huggingfacehub_api_token="my-api-key")
- """
-
- client: Any #: :meta private:
- repo_id: str = DEFAULT_REPO_ID
- """Model name to use."""
- task: Optional[str] = None
- """Task to call the model with.
- Should be a task that returns `generated_text` or `summary_text`."""
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
-
- huggingfacehub_api_token: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- huggingfacehub_api_token = get_from_dict_or_env(
- values, "huggingfacehub_api_token", "HUGGINGFACEHUB_API_TOKEN"
- )
- try:
- from huggingface_hub.inference_api import InferenceApi
-
- repo_id = values["repo_id"]
- client = InferenceApi(
- repo_id=repo_id,
- token=huggingfacehub_api_token,
- task=values.get("task"),
- )
- if client.task not in VALID_TASKS:
- raise ValueError(
- f"Got invalid task {client.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- values["client"] = client
- except ImportError:
- raise ValueError(
- "Could not import huggingface_hub python package. "
- "Please install it with `pip install huggingface_hub`."
- )
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"repo_id": self.repo_id, "task": self.task},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "huggingface_hub"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to HuggingFace Hub's inference endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = hf("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
- params = {**_model_kwargs, **kwargs}
- response = self.client(inputs=prompt, params=params)
- if "error" in response:
- raise ValueError(f"Error raised by inference API: {response['error']}")
- if self.client.task == "text-generation":
- # Text generation return includes the starter text.
- text = response[0]["generated_text"][len(prompt) :]
- elif self.client.task == "text2text-generation":
- text = response[0]["generated_text"]
- elif self.client.task == "summarization":
- text = response[0]["summary_text"]
- else:
- raise ValueError(
- f"Got invalid task {self.client.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- if stop is not None:
- # This is a bit hacky, but I can't figure out a better way to enforce
- # stop tokens when making calls to huggingface_hub.
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/huggingface_pipeline.py b/commune/modules/model/llm/huggingface_pipeline.py
deleted file mode 100644
index 9c3278792..000000000
--- a/commune/modules/model/llm/huggingface_pipeline.py
+++ /dev/null
@@ -1,184 +0,0 @@
-import importlib.util
-import logging
-from typing import Any, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra
-
-DEFAULT_MODEL_ID = "gpt2"
-DEFAULT_TASK = "text-generation"
-VALID_TASKS = ("text2text-generation", "text-generation", "summarization")
-
-logger = logging.getLogger(__name__)
-
-
-class HuggingFacePipeline(LLM):
- """HuggingFace Pipeline API.
-
- To use, you should have the ``transformers`` python package installed.
-
- Only supports `text-generation`, `text2text-generation` and `summarization` for now.
-
- Example using from_model_id:
- .. code-block:: python
-
- from langchain.llms import HuggingFacePipeline
- hf = HuggingFacePipeline.from_model_id(
- model_id="gpt2",
- task="text-generation",
- pipeline_kwargs={"max_new_tokens": 10},
- )
- Example passing pipeline in directly:
- .. code-block:: python
-
- from langchain.llms import HuggingFacePipeline
- from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
-
- model_id = "gpt2"
- tokenizer = AutoTokenizer.from_pretrained(model_id)
- model = AutoModelForCausalLM.from_pretrained(model_id)
- pipe = pipeline(
- "text-generation", model=model, tokenizer=tokenizer, max_new_tokens=10
- )
- hf = HuggingFacePipeline(pipeline=pipe)
- """
-
- pipeline: Any #: :meta private:
- model_id: str = DEFAULT_MODEL_ID
- """Model name to use."""
- model_kwargs: Optional[dict] = None
- """Key word arguments passed to the model."""
- pipeline_kwargs: Optional[dict] = None
- """Key word arguments passed to the pipeline."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @classmethod
- def from_model_id(
- cls,
- model_id: str,
- task: str,
- device: int = -1,
- model_kwargs: Optional[dict] = None,
- pipeline_kwargs: Optional[dict] = None,
- **kwargs: Any,
- ) -> LLM:
- """Construct the pipeline object from model_id and task."""
- try:
- from transformers import (
- AutoModelForCausalLM,
- AutoModelForSeq2SeqLM,
- AutoTokenizer,
- )
- from transformers import pipeline as hf_pipeline
-
- except ImportError:
- raise ValueError(
- "Could not import transformers python package. "
- "Please install it with `pip install transformers`."
- )
-
- _model_kwargs = model_kwargs or {}
- tokenizer = AutoTokenizer.from_pretrained(model_id, **_model_kwargs)
-
- try:
- if task == "text-generation":
- model = AutoModelForCausalLM.from_pretrained(model_id, **_model_kwargs)
- elif task in ("text2text-generation", "summarization"):
- model = AutoModelForSeq2SeqLM.from_pretrained(model_id, **_model_kwargs)
- else:
- raise ValueError(
- f"Got invalid task {task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- except ImportError as e:
- raise ValueError(
- f"Could not load the {task} model due to missing dependencies."
- ) from e
-
- if importlib.util.find_spec("torch") is not None:
- import torch
-
- cuda_device_count = torch.cuda.device_count()
- if device < -1 or (device >= cuda_device_count):
- raise ValueError(
- f"Got device=={device}, "
- f"device is required to be within [-1, {cuda_device_count})"
- )
- if device < 0 and cuda_device_count > 0:
- logger.warning(
- "Device has %d GPUs available. "
- "Provide device={deviceId} to `from_model_id` to use available"
- "GPUs for execution. deviceId is -1 (default) for CPU and "
- "can be a positive integer associated with CUDA device id.",
- cuda_device_count,
- )
- if "trust_remote_code" in _model_kwargs:
- _model_kwargs = {
- k: v for k, v in _model_kwargs.items() if k != "trust_remote_code"
- }
- _pipeline_kwargs = pipeline_kwargs or {}
- pipeline = hf_pipeline(
- task=task,
- model=model,
- tokenizer=tokenizer,
- device=device,
- model_kwargs=_model_kwargs,
- **_pipeline_kwargs,
- )
- if pipeline.task not in VALID_TASKS:
- raise ValueError(
- f"Got invalid task {pipeline.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- return cls(
- pipeline=pipeline,
- model_id=model_id,
- model_kwargs=_model_kwargs,
- pipeline_kwargs=_pipeline_kwargs,
- **kwargs,
- )
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "model_id": self.model_id,
- "model_kwargs": self.model_kwargs,
- "pipeline_kwargs": self.pipeline_kwargs,
- }
-
- @property
- def _llm_type(self) -> str:
- return "huggingface_pipeline"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- response = self.pipeline(prompt)
- if self.pipeline.task == "text-generation":
- # Text generation return includes the starter text.
- text = response[0]["generated_text"][len(prompt) :]
- elif self.pipeline.task == "text2text-generation":
- text = response[0]["generated_text"]
- elif self.pipeline.task == "summarization":
- text = response[0]["summary_text"]
- else:
- raise ValueError(
- f"Got invalid task {self.pipeline.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- if stop:
- # This is a bit hacky, but I can't figure out a better way to enforce
- # stop tokens when making calls to huggingface_hub.
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/huggingface_text_gen_inference.py b/commune/modules/model/llm/huggingface_text_gen_inference.py
deleted file mode 100644
index 683b2f4dd..000000000
--- a/commune/modules/model/llm/huggingface_text_gen_inference.py
+++ /dev/null
@@ -1,301 +0,0 @@
-import logging
-from typing import Any, AsyncIterator, Dict, Iterator, List, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.schema.output import GenerationChunk
-from langchain.utils import get_pydantic_field_names
-
-logger = logging.getLogger(__name__)
-
-
-class HuggingFaceTextGenInference(LLM):
- """
- HuggingFace text generation API.
-
- To use, you should have the `text-generation` python package installed and
- a text-generation server running.
-
- Example:
- .. code-block:: python
-
- # Basic Example (no streaming)
- llm = HuggingFaceTextGenInference(
- inference_server_url="http://localhost:8010/",
- max_new_tokens=512,
- top_k=10,
- top_p=0.95,
- typical_p=0.95,
- temperature=0.01,
- repetition_penalty=1.03,
- )
- print(llm("What is Deep Learning?"))
-
- # Streaming response example
- from langchain.callbacks import streaming_stdout
-
- callbacks = [streaming_stdout.StreamingStdOutCallbackHandler()]
- llm = HuggingFaceTextGenInference(
- inference_server_url="http://localhost:8010/",
- max_new_tokens=512,
- top_k=10,
- top_p=0.95,
- typical_p=0.95,
- temperature=0.01,
- repetition_penalty=1.03,
- callbacks=callbacks,
- streaming=True
- )
- print(llm("What is Deep Learning?"))
-
- """
-
- max_new_tokens: int = 512
- """Maximum number of generated tokens"""
- top_k: Optional[int] = None
- """The number of highest probability vocabulary tokens to keep for
- top-k-filtering."""
- top_p: Optional[float] = 0.95
- """If set to < 1, only the smallest set of most probable tokens with probabilities
- that add up to `top_p` or higher are kept for generation."""
- typical_p: Optional[float] = 0.95
- """Typical Decoding mass. See [Typical Decoding for Natural Language
- Generation](https://arxiv.org/abs/2202.00666) for more information."""
- temperature: Optional[float] = 0.8
- """The value used to module the logits distribution."""
- repetition_penalty: Optional[float] = None
- """The parameter for repetition penalty. 1.0 means no penalty.
- See [this paper](https://arxiv.org/pdf/1909.05858.pdf) for more details."""
- return_full_text: bool = False
- """Whether to prepend the prompt to the generated text"""
- truncate: Optional[int] = None
- """Truncate inputs tokens to the given size"""
- stop_sequences: List[str] = Field(default_factory=list)
- """Stop generating tokens if a member of `stop_sequences` is generated"""
- seed: Optional[int] = None
- """Random sampling seed"""
- inference_server_url: str = ""
- """text-generation-inference instance base url"""
- timeout: int = 120
- """Timeout in seconds"""
- streaming: bool = False
- """Whether to generate a stream of tokens asynchronously"""
- do_sample: bool = False
- """Activate logits sampling"""
- watermark: bool = False
- """Watermarking with [A Watermark for Large Language Models]
- (https://arxiv.org/abs/2301.10226)"""
- server_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any text-generation-inference server parameters not explicitly specified"""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `call` not explicitly specified"""
- client: Any
- async_client: Any
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = get_pydantic_field_names(cls)
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- if field_name not in all_required_field_names:
- logger.warning(
- f"""WARNING! {field_name} is not default parameter.
- {field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
-
- invalid_model_kwargs = all_required_field_names.intersection(extra.keys())
- if invalid_model_kwargs:
- raise ValueError(
- f"Parameters {invalid_model_kwargs} should be specified explicitly. "
- f"Instead they were passed in as part of `model_kwargs` parameter."
- )
-
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that python package exists in environment."""
-
- try:
- import text_generation
-
- values["client"] = text_generation.Client(
- values["inference_server_url"],
- timeout=values["timeout"],
- **values["server_kwargs"],
- )
- values["async_client"] = text_generation.AsyncClient(
- values["inference_server_url"],
- timeout=values["timeout"],
- **values["server_kwargs"],
- )
- except ImportError:
- raise ImportError(
- "Could not import text_generation python package. "
- "Please install it with `pip install text_generation`."
- )
- return values
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "huggingface_textgen_inference"
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling text generation inference API."""
- return {
- "max_new_tokens": self.max_new_tokens,
- "top_k": self.top_k,
- "top_p": self.top_p,
- "typical_p": self.typical_p,
- "temperature": self.temperature,
- "repetition_penalty": self.repetition_penalty,
- "return_full_text": self.return_full_text,
- "truncate": self.truncate,
- "stop_sequences": self.stop_sequences,
- "seed": self.seed,
- "do_sample": self.do_sample,
- "watermark": self.watermark,
- **self.model_kwargs,
- }
-
- def _invocation_params(
- self, runtime_stop: Optional[List[str]], **kwargs: Any
- ) -> Dict[str, Any]:
- params = {**self._default_params, **kwargs}
- params["stop_sequences"] = params["stop_sequences"] + (runtime_stop or [])
- return params
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- if self.streaming:
- completion = ""
- for chunk in self._stream(prompt, stop, run_manager, **kwargs):
- completion += chunk.text
- return completion
-
- invocation_params = self._invocation_params(stop, **kwargs)
- res = self.client.generate(prompt, **invocation_params)
- # remove stop sequences from the end of the generated text
- for stop_seq in invocation_params["stop_sequences"]:
- if stop_seq in res.generated_text:
- res.generated_text = res.generated_text[
- : res.generated_text.index(stop_seq)
- ]
- return res.generated_text
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- if self.streaming:
- completion = ""
- async for chunk in self._astream(prompt, stop, run_manager, **kwargs):
- completion += chunk.text
- return completion
-
- invocation_params = self._invocation_params(stop, **kwargs)
- res = await self.async_client.generate(prompt, **invocation_params)
- # remove stop sequences from the end of the generated text
- for stop_seq in invocation_params["stop_sequences"]:
- if stop_seq in res.generated_text:
- res.generated_text = res.generated_text[
- : res.generated_text.index(stop_seq)
- ]
- return res.generated_text
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- invocation_params = self._invocation_params(stop, **kwargs)
-
- for res in self.client.generate_stream(prompt, **invocation_params):
- # identify stop sequence in generated text, if any
- stop_seq_found: Optional[str] = None
- for stop_seq in invocation_params["stop_sequences"]:
- if stop_seq in res.token.text:
- stop_seq_found = stop_seq
-
- # identify text to yield
- text: Optional[str] = None
- if res.token.special:
- text = None
- elif stop_seq_found:
- text = res.token.text[: res.token.text.index(stop_seq_found)]
- else:
- text = res.token.text
-
- # yield text, if any
- if text:
- chunk = GenerationChunk(text=text)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(chunk.text)
-
- # break if stop sequence found
- if stop_seq_found:
- break
-
- async def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- invocation_params = self._invocation_params(stop, **kwargs)
-
- async for res in self.async_client.generate_stream(prompt, **invocation_params):
- # identify stop sequence in generated text, if any
- stop_seq_found: Optional[str] = None
- for stop_seq in invocation_params["stop_sequences"]:
- if stop_seq in res.token.text:
- stop_seq_found = stop_seq
-
- # identify text to yield
- text: Optional[str] = None
- if res.token.special:
- text = None
- elif stop_seq_found:
- text = res.token.text[: res.token.text.index(stop_seq_found)]
- else:
- text = res.token.text
-
- # yield text, if any
- if text:
- chunk = GenerationChunk(text=text)
- yield chunk
- if run_manager:
- await run_manager.on_llm_new_token(chunk.text)
-
- # break if stop sequence found
- if stop_seq_found:
- break
diff --git a/commune/modules/model/llm/human.py b/commune/modules/model/llm/human.py
deleted file mode 100644
index d6ea10b8e..000000000
--- a/commune/modules/model/llm/human.py
+++ /dev/null
@@ -1,84 +0,0 @@
-from typing import Any, Callable, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Field
-
-
-def _display_prompt(prompt: str) -> None:
- """Displays the given prompt to the user."""
- print(f"\n{prompt}")
-
-
-def _collect_user_input(
- separator: Optional[str] = None, stop: Optional[List[str]] = None
-) -> str:
- """Collects and returns user input as a single string."""
- separator = separator or "\n"
- lines = []
-
- while True:
- line = input()
- if not line:
- break
- lines.append(line)
-
- if stop and any(seq in line for seq in stop):
- break
- # Combine all lines into a single string
- multi_line_input = separator.join(lines)
- return multi_line_input
-
-
-class HumanInputLLM(LLM):
- """
- It returns user input as the response.
- """
-
- input_func: Callable = Field(default_factory=lambda: _collect_user_input)
- prompt_func: Callable[[str], None] = Field(default_factory=lambda: _display_prompt)
- separator: str = "\n"
- input_kwargs: Mapping[str, Any] = {}
- prompt_kwargs: Mapping[str, Any] = {}
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """
- Returns an empty dictionary as there are no identifying parameters.
- """
- return {}
-
- @property
- def _llm_type(self) -> str:
- """Returns the type of LLM."""
- return "human-input"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """
- Displays the prompt to the user and returns their input as a response.
-
- Args:
- prompt (str): The prompt to be displayed to the user.
- stop (Optional[List[str]]): A list of stop strings.
- run_manager (Optional[CallbackManagerForLLMRun]): Currently not used.
-
- Returns:
- str: The user's input as a response.
- """
- self.prompt_func(prompt, **self.prompt_kwargs)
- user_input = self.input_func(
- separator=self.separator, stop=stop, **self.input_kwargs
- )
-
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the human themselves
- user_input = enforce_stop_tokens(user_input, stop)
- return user_input
diff --git a/commune/modules/model/llm/javelin_ai_gateway.py b/commune/modules/model/llm/javelin_ai_gateway.py
deleted file mode 100644
index 7effebb6b..000000000
--- a/commune/modules/model/llm/javelin_ai_gateway.py
+++ /dev/null
@@ -1,152 +0,0 @@
-from __future__ import annotations
-
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import BaseModel, Extra
-
-
-# Ignoring type because below is valid pydantic code
-# Unexpected keyword argument "extra" for "__init_subclass__" of "object"
-class Params(BaseModel, extra=Extra.allow): # type: ignore[call-arg]
- """Parameters for the Javelin AI Gateway LLM."""
-
- temperature: float = 0.0
- stop: Optional[List[str]] = None
- max_tokens: Optional[int] = None
-
-
-class JavelinAIGateway(LLM):
- """
- Wrapper around completions LLMs in the Javelin AI Gateway.
-
- To use, you should have the ``javelin_sdk`` python package installed.
- For more information, see https://docs.getjavelin.io
-
- Example:
- .. code-block:: python
-
- from langchain.llms import JavelinAIGateway
-
- completions = JavelinAIGateway(
- gateway_uri="",
- route="",
- params={
- "temperature": 0.1
- }
- )
- """
-
- route: str
- """The route to use for the Javelin AI Gateway API."""
-
- client: Optional[Any] = None
- """The Javelin AI Gateway client."""
-
- gateway_uri: Optional[str] = None
- """The URI of the Javelin AI Gateway API."""
-
- params: Optional[Params] = None
- """Parameters for the Javelin AI Gateway API."""
-
- javelin_api_key: Optional[str] = None
- """The API key for the Javelin AI Gateway API."""
-
- def __init__(self, **kwargs: Any):
- try:
- from javelin_sdk import (
- JavelinClient,
- UnauthorizedError,
- )
- except ImportError:
- raise ImportError(
- "Could not import javelin_sdk python package. "
- "Please install it with `pip install javelin_sdk`."
- )
- super().__init__(**kwargs)
- if self.gateway_uri:
- try:
- self.client = JavelinClient(
- base_url=self.gateway_uri, api_key=self.javelin_api_key
- )
- except UnauthorizedError as e:
- raise ValueError("Javelin: Incorrect API Key.") from e
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Javelin AI Gateway API."""
- params: Dict[str, Any] = {
- "gateway_uri": self.gateway_uri,
- "route": self.route,
- "javelin_api_key": self.javelin_api_key,
- **(self.params.dict() if self.params else {}),
- }
- return params
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return self._default_params
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the Javelin AI Gateway API."""
- data: Dict[str, Any] = {
- "prompt": prompt,
- **(self.params.dict() if self.params else {}),
- }
- if s := (stop or (self.params.stop if self.params else None)):
- data["stop"] = s
-
- if self.client is not None:
- resp = self.client.query_route(self.route, query_body=data)
- else:
- raise ValueError("Javelin client is not initialized.")
-
- resp_dict = resp.dict()
-
- try:
- return resp_dict["llm_response"]["choices"][0]["text"]
- except KeyError:
- return ""
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call async the Javelin AI Gateway API."""
- data: Dict[str, Any] = {
- "prompt": prompt,
- **(self.params.dict() if self.params else {}),
- }
- if s := (stop or (self.params.stop if self.params else None)):
- data["stop"] = s
-
- if self.client is not None:
- resp = await self.client.aquery_route(self.route, query_body=data)
- else:
- raise ValueError("Javelin client is not initialized.")
-
- resp_dict = resp.dict()
-
- try:
- return resp_dict["llm_response"]["choices"][0]["text"]
- except KeyError:
- return ""
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "javelin-ai-gateway"
diff --git a/commune/modules/model/llm/koboldai.py b/commune/modules/model/llm/koboldai.py
deleted file mode 100644
index ac0602794..000000000
--- a/commune/modules/model/llm/koboldai.py
+++ /dev/null
@@ -1,198 +0,0 @@
-import logging
-from typing import Any, Dict, List, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-
-logger = logging.getLogger(__name__)
-
-
-def clean_url(url: str) -> str:
- """Remove trailing slash and /api from url if present."""
- if url.endswith("/api"):
- return url[:-4]
- elif url.endswith("/"):
- return url[:-1]
- else:
- return url
-
-
-class KoboldApiLLM(LLM):
- """Kobold API language model.
-
- It includes several fields that can be used to control the text generation process.
-
- To use this class, instantiate it with the required parameters and call it with a
- prompt to generate text. For example:
-
- kobold = KoboldApiLLM(endpoint="http://localhost:5000")
- result = kobold("Write a story about a dragon.")
-
- This will send a POST request to the Kobold API with the provided prompt and
- generate text.
- """
-
- endpoint: str
- """The API endpoint to use for generating text."""
-
- use_story: Optional[bool] = False
- """ Whether or not to use the story from the KoboldAI GUI when generating text. """
-
- use_authors_note: Optional[bool] = False
- """Whether to use the author's note from the KoboldAI GUI when generating text.
-
- This has no effect unless use_story is also enabled.
- """
-
- use_world_info: Optional[bool] = False
- """Whether to use the world info from the KoboldAI GUI when generating text."""
-
- use_memory: Optional[bool] = False
- """Whether to use the memory from the KoboldAI GUI when generating text."""
-
- max_context_length: Optional[int] = 1600
- """Maximum number of tokens to send to the model.
-
- minimum: 1
- """
-
- max_length: Optional[int] = 80
- """Number of tokens to generate.
-
- maximum: 512
- minimum: 1
- """
-
- rep_pen: Optional[float] = 1.12
- """Base repetition penalty value.
-
- minimum: 1
- """
-
- rep_pen_range: Optional[int] = 1024
- """Repetition penalty range.
-
- minimum: 0
- """
-
- rep_pen_slope: Optional[float] = 0.9
- """Repetition penalty slope.
-
- minimum: 0
- """
-
- temperature: Optional[float] = 0.6
- """Temperature value.
-
- exclusiveMinimum: 0
- """
-
- tfs: Optional[float] = 0.9
- """Tail free sampling value.
-
- maximum: 1
- minimum: 0
- """
-
- top_a: Optional[float] = 0.9
- """Top-a sampling value.
-
- minimum: 0
- """
-
- top_p: Optional[float] = 0.95
- """Top-p sampling value.
-
- maximum: 1
- minimum: 0
- """
-
- top_k: Optional[int] = 0
- """Top-k sampling value.
-
- minimum: 0
- """
-
- typical: Optional[float] = 0.5
- """Typical sampling value.
-
- maximum: 1
- minimum: 0
- """
-
- @property
- def _llm_type(self) -> str:
- return "koboldai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the API and return the output.
-
- Args:
- prompt: The prompt to use for generation.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The generated text.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import KoboldApiLLM
-
- llm = KoboldApiLLM(endpoint="http://localhost:5000")
- llm("Write a story about dragons.")
- """
- data: Dict[str, Any] = {
- "prompt": prompt,
- "use_story": self.use_story,
- "use_authors_note": self.use_authors_note,
- "use_world_info": self.use_world_info,
- "use_memory": self.use_memory,
- "max_context_length": self.max_context_length,
- "max_length": self.max_length,
- "rep_pen": self.rep_pen,
- "rep_pen_range": self.rep_pen_range,
- "rep_pen_slope": self.rep_pen_slope,
- "temperature": self.temperature,
- "tfs": self.tfs,
- "top_a": self.top_a,
- "top_p": self.top_p,
- "top_k": self.top_k,
- "typical": self.typical,
- }
-
- if stop is not None:
- data["stop_sequence"] = stop
-
- response = requests.post(
- f"{clean_url(self.endpoint)}/api/v1/generate", json=data
- )
-
- response.raise_for_status()
- json_response = response.json()
-
- if (
- "results" in json_response
- and len(json_response["results"]) > 0
- and "text" in json_response["results"][0]
- ):
- text = json_response["results"][0]["text"].strip()
-
- if stop is not None:
- for sequence in stop:
- if text.endswith(sequence):
- text = text[: -len(sequence)].rstrip()
-
- return text
- else:
- raise ValueError(
- f"Unexpected response format from Kobold API: {json_response}"
- )
diff --git a/commune/modules/model/llm/llamacpp.py b/commune/modules/model/llm/llamacpp.py
deleted file mode 100644
index 0e4b7e8f6..000000000
--- a/commune/modules/model/llm/llamacpp.py
+++ /dev/null
@@ -1,358 +0,0 @@
-from __future__ import annotations
-
-import logging
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Union
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema.output import GenerationChunk
-from langchain.utils import get_pydantic_field_names
-from langchain.utils.utils import build_extra_kwargs
-
-if TYPE_CHECKING:
- from llama_cpp import LlamaGrammar
-
-logger = logging.getLogger(__name__)
-
-
-class LlamaCpp(LLM):
- """llama.cpp model.
-
- To use, you should have the llama-cpp-python library installed, and provide the
- path to the Llama model as a named parameter to the constructor.
- Check out: https://github.com/abetlen/llama-cpp-python
-
- Example:
- .. code-block:: python
-
- from langchain.llms import LlamaCpp
- llm = LlamaCpp(model_path="/path/to/llama/model")
- """
-
- client: Any #: :meta private:
- model_path: str
- """The path to the Llama model file."""
-
- lora_base: Optional[str] = None
- """The path to the Llama LoRA base model."""
-
- lora_path: Optional[str] = None
- """The path to the Llama LoRA. If None, no LoRa is loaded."""
-
- n_ctx: int = Field(512, alias="n_ctx")
- """Token context window."""
-
- n_parts: int = Field(-1, alias="n_parts")
- """Number of parts to split the model into.
- If -1, the number of parts is automatically determined."""
-
- seed: int = Field(-1, alias="seed")
- """Seed. If -1, a random seed is used."""
-
- f16_kv: bool = Field(True, alias="f16_kv")
- """Use half-precision for key/value cache."""
-
- logits_all: bool = Field(False, alias="logits_all")
- """Return logits for all tokens, not just the last token."""
-
- vocab_only: bool = Field(False, alias="vocab_only")
- """Only load the vocabulary, no weights."""
-
- use_mlock: bool = Field(False, alias="use_mlock")
- """Force system to keep model in RAM."""
-
- n_threads: Optional[int] = Field(None, alias="n_threads")
- """Number of threads to use.
- If None, the number of threads is automatically determined."""
-
- n_batch: Optional[int] = Field(8, alias="n_batch")
- """Number of tokens to process in parallel.
- Should be a number between 1 and n_ctx."""
-
- n_gpu_layers: Optional[int] = Field(None, alias="n_gpu_layers")
- """Number of layers to be loaded into gpu memory. Default None."""
-
- suffix: Optional[str] = Field(None)
- """A suffix to append to the generated text. If None, no suffix is appended."""
-
- max_tokens: Optional[int] = 256
- """The maximum number of tokens to generate."""
-
- temperature: Optional[float] = 0.8
- """The temperature to use for sampling."""
-
- top_p: Optional[float] = 0.95
- """The top-p value to use for sampling."""
-
- logprobs: Optional[int] = Field(None)
- """The number of logprobs to return. If None, no logprobs are returned."""
-
- echo: Optional[bool] = False
- """Whether to echo the prompt."""
-
- stop: Optional[List[str]] = []
- """A list of strings to stop generation when encountered."""
-
- repeat_penalty: Optional[float] = 1.1
- """The penalty to apply to repeated tokens."""
-
- top_k: Optional[int] = 40
- """The top-k value to use for sampling."""
-
- last_n_tokens_size: Optional[int] = 64
- """The number of tokens to look back when applying the repeat_penalty."""
-
- use_mmap: Optional[bool] = True
- """Whether to keep the model loaded in RAM"""
-
- rope_freq_scale: float = 1.0
- """Scale factor for rope sampling."""
-
- rope_freq_base: float = 10000.0
- """Base frequency for rope sampling."""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Any additional parameters to pass to llama_cpp.Llama."""
-
- streaming: bool = True
- """Whether to stream the results, token by token."""
-
- grammar_path: Optional[Union[str, Path]] = None
- """
- grammar_path: Path to the .gbnf file that defines formal grammars
- for constraining model outputs. For instance, the grammar can be used
- to force the model to generate valid JSON or to speak exclusively in emojis. At most
- one of grammar_path and grammar should be passed in.
- """
- grammar: Optional[Union[str, LlamaGrammar]] = None
- """
- grammar: formal grammar for constraining model outputs. For instance, the grammar
- can be used to force the model to generate valid JSON or to speak exclusively in
- emojis. At most one of grammar_path and grammar should be passed in.
- """
-
- verbose: bool = True
- """Print verbose output to stderr."""
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that llama-cpp-python library is installed."""
- try:
- from llama_cpp import Llama, LlamaGrammar
- except ImportError:
- raise ImportError(
- "Could not import llama-cpp-python library. "
- "Please install the llama-cpp-python library to "
- "use this embedding model: pip install llama-cpp-python"
- )
-
- model_path = values["model_path"]
- model_param_names = [
- "rope_freq_scale",
- "rope_freq_base",
- "lora_path",
- "lora_base",
- "n_ctx",
- "n_parts",
- "seed",
- "f16_kv",
- "logits_all",
- "vocab_only",
- "use_mlock",
- "n_threads",
- "n_batch",
- "use_mmap",
- "last_n_tokens_size",
- "verbose",
- ]
- model_params = {k: values[k] for k in model_param_names}
- # For backwards compatibility, only include if non-null.
- if values["n_gpu_layers"] is not None:
- model_params["n_gpu_layers"] = values["n_gpu_layers"]
-
- model_params.update(values["model_kwargs"])
-
- try:
- values["client"] = Llama(model_path, **model_params)
- except Exception as e:
- raise ValueError(
- f"Could not load Llama model from path: {model_path}. "
- f"Received error {e}"
- )
-
- if values["grammar"] and values["grammar_path"]:
- grammar = values["grammar"]
- grammar_path = values["grammar_path"]
- raise ValueError(
- "Can only pass in one of grammar and grammar_path. Received "
- f"{grammar=} and {grammar_path=}."
- )
- elif isinstance(values["grammar"], str):
- values["grammar"] = LlamaGrammar.from_string(values["grammar"])
- elif values["grammar_path"]:
- values["grammar"] = LlamaGrammar.from_file(values["grammar_path"])
- else:
- pass
- return values
-
- @root_validator(pre=True)
- def build_model_kwargs(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = get_pydantic_field_names(cls)
- extra = values.get("model_kwargs", {})
- values["model_kwargs"] = build_extra_kwargs(
- extra, values, all_required_field_names
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling llama_cpp."""
- params = {
- "suffix": self.suffix,
- "max_tokens": self.max_tokens,
- "temperature": self.temperature,
- "top_p": self.top_p,
- "logprobs": self.logprobs,
- "echo": self.echo,
- "stop_sequences": self.stop, # key here is convention among LLM classes
- "repeat_penalty": self.repeat_penalty,
- "top_k": self.top_k,
- }
- if self.grammar:
- params["grammar"] = self.grammar
- return params
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_path": self.model_path}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "llamacpp"
-
- def _get_parameters(self, stop: Optional[List[str]] = None) -> Dict[str, Any]:
- """
- Performs sanity check, preparing parameters in format needed by llama_cpp.
-
- Args:
- stop (Optional[List[str]]): List of stop sequences for llama_cpp.
-
- Returns:
- Dictionary containing the combined parameters.
- """
-
- # Raise error if stop sequences are in both input and default params
- if self.stop and stop is not None:
- raise ValueError("`stop` found in both the input and default params.")
-
- params = self._default_params
-
- # llama_cpp expects the "stop" key not this, so we remove it:
- params.pop("stop_sequences")
-
- # then sets it as configured, or default to an empty list:
- params["stop"] = self.stop or stop or []
-
- return params
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the Llama model and return the output.
-
- Args:
- prompt: The prompt to use for generation.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The generated text.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import LlamaCpp
- llm = LlamaCpp(model_path="/path/to/local/llama/model.bin")
- llm("This is a prompt.")
- """
- if self.streaming:
- # If streaming is enabled, we use the stream
- # method that yields as they are generated
- # and return the combined strings from the first choices's text:
- combined_text_output = ""
- for chunk in self._stream(
- prompt=prompt,
- stop=stop,
- run_manager=run_manager,
- **kwargs,
- ):
- combined_text_output += chunk.text
- return combined_text_output
- else:
- params = self._get_parameters(stop)
- params = {**params, **kwargs}
- result = self.client(prompt=prompt, **params)
- return result["choices"][0]["text"]
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- """Yields results objects as they are generated in real time.
-
- It also calls the callback manager's on_llm_new_token event with
- similar parameters to the OpenAI LLM class method of the same name.
-
- Args:
- prompt: The prompts to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- A generator representing the stream of tokens being generated.
-
- Yields:
- A dictionary like objects containing a string token and metadata.
- See llama-cpp-python docs and below for more.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import LlamaCpp
- llm = LlamaCpp(
- model_path="/path/to/local/model.bin",
- temperature = 0.5
- )
- for chunk in llm.stream("Ask 'Hi, how are you?' like a pirate:'",
- stop=["'","\n"]):
- result = chunk["choices"][0]
- print(result["text"], end='', flush=True)
-
- """
- params = {**self._get_parameters(stop), **kwargs}
- result = self.client(prompt=prompt, stream=True, **params)
- for part in result:
- logprobs = part["choices"][0].get("logprobs", None)
- chunk = GenerationChunk(
- text=part["choices"][0]["text"],
- generation_info={"logprobs": logprobs},
- )
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(
- token=chunk.text, verbose=self.verbose, log_probs=logprobs
- )
-
- def get_num_tokens(self, text: str) -> int:
- tokenized_text = self.client.tokenize(text.encode("utf-8"))
- return len(tokenized_text)
diff --git a/commune/modules/model/llm/loading.py b/commune/modules/model/llm/loading.py
deleted file mode 100644
index d96039081..000000000
--- a/commune/modules/model/llm/loading.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""Base interface for loading large language model APIs."""
-import json
-from pathlib import Path
-from typing import Union
-
-import yaml
-
-from langchain.llms import type_to_cls_dict
-from langchain.llms.base import BaseLLM
-
-
-def load_llm_from_config(config: dict) -> BaseLLM:
- """Load LLM from Config Dict."""
- if "_type" not in config:
- raise ValueError("Must specify an LLM Type in config")
- config_type = config.pop("_type")
-
- if config_type not in type_to_cls_dict:
- raise ValueError(f"Loading {config_type} LLM not supported")
-
- llm_cls = type_to_cls_dict[config_type]
- return llm_cls(**config)
-
-
-def load_llm(file: Union[str, Path]) -> BaseLLM:
- """Load LLM from file."""
- # Convert file to Path object.
- if isinstance(file, str):
- file_path = Path(file)
- else:
- file_path = file
- # Load from either json or yaml.
- if file_path.suffix == ".json":
- with open(file_path) as f:
- config = json.load(f)
- elif file_path.suffix == ".yaml":
- with open(file_path, "r") as f:
- config = yaml.safe_load(f)
- else:
- raise ValueError("File type must be json or yaml")
- # Load the LLM from the config now.
- return load_llm_from_config(config)
diff --git a/commune/modules/model/llm/manifest.py b/commune/modules/model/llm/manifest.py
deleted file mode 100644
index 5e2416ab4..000000000
--- a/commune/modules/model/llm/manifest.py
+++ /dev/null
@@ -1,63 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, root_validator
-
-
-class ManifestWrapper(LLM):
- """HazyResearch's Manifest library."""
-
- client: Any #: :meta private:
- llm_kwargs: Optional[Dict] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that python package exists in environment."""
- try:
- from manifest import Manifest
-
- if not isinstance(values["client"], Manifest):
- raise ValueError
- except ImportError:
- raise ImportError(
- "Could not import manifest python package. "
- "Please install it with `pip install manifest-ml`."
- )
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- kwargs = self.llm_kwargs or {}
- return {
- **self.client.client_pool.get_current_client().get_model_params(),
- **kwargs,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "manifest"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to LLM through Manifest."""
- if stop is not None and len(stop) != 1:
- raise NotImplementedError(
- f"Manifest currently only supports a single stop token, got {stop}"
- )
- params = self.llm_kwargs or {}
- params = {**params, **kwargs}
- if stop is not None:
- params["stop_token"] = stop
- return self.client.run(prompt, **params)
diff --git a/commune/modules/model/llm/minimax.py b/commune/modules/model/llm/minimax.py
deleted file mode 100644
index 318839f39..000000000
--- a/commune/modules/model/llm/minimax.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""Wrapper around Minimax APIs."""
-from __future__ import annotations
-
-import logging
-from typing import (
- Any,
- Dict,
- List,
- Optional,
-)
-
-import requests
-
-from langchain.callbacks.manager import (
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import BaseModel, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class _MinimaxEndpointClient(BaseModel):
- """An API client that talks to a Minimax llm endpoint."""
-
- host: str
- group_id: str
- api_key: str
- api_url: str
-
- @root_validator(pre=True, allow_reuse=True)
- def set_api_url(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- if "api_url" not in values:
- host = values["host"]
- group_id = values["group_id"]
- api_url = f"{host}/v1/text/chatcompletion?GroupId={group_id}"
- values["api_url"] = api_url
- return values
-
- def post(self, request: Any) -> Any:
- headers = {"Authorization": f"Bearer {self.api_key}"}
- response = requests.post(self.api_url, headers=headers, json=request)
- # TODO: error handling and automatic retries
- if not response.ok:
- raise ValueError(f"HTTP {response.status_code} error: {response.text}")
- if response.json()["base_resp"]["status_code"] > 0:
- raise ValueError(
- f"API {response.json()['base_resp']['status_code']}"
- f" error: {response.json()['base_resp']['status_msg']}"
- )
- return response.json()["reply"]
-
-
-class MinimaxCommon(BaseModel):
- _client: _MinimaxEndpointClient
- model: str = "abab5.5-chat"
- """Model name to use."""
- max_tokens: int = 256
- """Denotes the number of tokens to predict per generation."""
- temperature: float = 0.7
- """A non-negative float that tunes the degree of randomness in generation."""
- top_p: float = 0.95
- """Total probability mass of tokens to consider at each step."""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not explicitly specified."""
- minimax_api_host: Optional[str] = None
- minimax_group_id: Optional[str] = None
- minimax_api_key: Optional[str] = None
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["minimax_api_key"] = get_from_dict_or_env(
- values, "minimax_api_key", "MINIMAX_API_KEY"
- )
- values["minimax_group_id"] = get_from_dict_or_env(
- values, "minimax_group_id", "MINIMAX_GROUP_ID"
- )
- # Get custom api url from environment.
- values["minimax_api_host"] = get_from_dict_or_env(
- values,
- "minimax_api_host",
- "MINIMAX_API_HOST",
- default="https://api.minimax.chat",
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- return {
- "model": self.model,
- "tokens_to_generate": self.max_tokens,
- "temperature": self.temperature,
- "top_p": self.top_p,
- **self.model_kwargs,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model": self.model}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "minimax"
-
- def __init__(self, **data: Any):
- super().__init__(**data)
- self._client = _MinimaxEndpointClient(
- host=self.minimax_api_host,
- api_key=self.minimax_api_key,
- group_id=self.minimax_group_id,
- )
-
-
-class Minimax(MinimaxCommon, LLM):
- """Wrapper around Minimax large language models.
- To use, you should have the environment variable
- ``MINIMAX_API_KEY`` and ``MINIMAX_GROUP_ID`` set with your API key,
- or pass them as a named parameter to the constructor.
- Example:
- . code-block:: python
- from langchain.llms.minimax import Minimax
- minimax = Minimax(model="", minimax_api_key="my-api-key",
- minimax_group_id="my-group-id")
- """
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- r"""Call out to Minimax's completion endpoint to chat
- Args:
- prompt: The prompt to pass into the model.
- Returns:
- The string generated by the model.
- Example:
- .. code-block:: python
- response = minimax("Tell me a joke.")
- """
- request = self._default_params
- request["messages"] = [{"sender_type": "USER", "text": prompt}]
- request.update(kwargs)
- text = self._client.post(request)
- if stop is not None:
- # This is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
-
- return text
diff --git a/commune/modules/model/llm/mlflow_ai_gateway.py b/commune/modules/model/llm/mlflow_ai_gateway.py
deleted file mode 100644
index dcb75c519..000000000
--- a/commune/modules/model/llm/mlflow_ai_gateway.py
+++ /dev/null
@@ -1,99 +0,0 @@
-from __future__ import annotations
-
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import BaseModel, Extra
-
-
-# Ignoring type because below is valid pydantic code
-# Unexpected keyword argument "extra" for "__init_subclass__" of "object"
-class Params(BaseModel, extra=Extra.allow): # type: ignore[call-arg]
- """Parameters for the MLflow AI Gateway LLM."""
-
- temperature: float = 0.0
- candidate_count: int = 1
- """The number of candidates to return."""
- stop: Optional[List[str]] = None
- max_tokens: Optional[int] = None
-
-
-class MlflowAIGateway(LLM):
- """
- Wrapper around completions LLMs in the MLflow AI Gateway.
-
- To use, you should have the ``mlflow[gateway]`` python package installed.
- For more information, see https://mlflow.org/docs/latest/gateway/index.html.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import MlflowAIGateway
-
- completions = MlflowAIGateway(
- gateway_uri="",
- route="",
- params={
- "temperature": 0.1
- }
- )
- """
-
- route: str
- gateway_uri: Optional[str] = None
- params: Optional[Params] = None
-
- def __init__(self, **kwargs: Any):
- try:
- import mlflow.gateway
- except ImportError as e:
- raise ImportError(
- "Could not import `mlflow.gateway` module. "
- "Please install it with `pip install mlflow[gateway]`."
- ) from e
-
- super().__init__(**kwargs)
- if self.gateway_uri:
- mlflow.gateway.set_gateway_uri(self.gateway_uri)
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- params: Dict[str, Any] = {
- "gateway_uri": self.gateway_uri,
- "route": self.route,
- **(self.params.dict() if self.params else {}),
- }
- return params
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- return self._default_params
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- try:
- import mlflow.gateway
- except ImportError as e:
- raise ImportError(
- "Could not import `mlflow.gateway` module. "
- "Please install it with `pip install mlflow[gateway]`."
- ) from e
-
- data: Dict[str, Any] = {
- "prompt": prompt,
- **(self.params.dict() if self.params else {}),
- }
- if s := (stop or (self.params.stop if self.params else None)):
- data["stop"] = s
- resp = mlflow.gateway.query(self.route, data=data)
- return resp["candidates"][0]["text"]
-
- @property
- def _llm_type(self) -> str:
- return "mlflow-ai-gateway"
diff --git a/commune/modules/model/llm/modal.py b/commune/modules/model/llm/modal.py
deleted file mode 100644
index 9f1f42269..000000000
--- a/commune/modules/model/llm/modal.py
+++ /dev/null
@@ -1,100 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-
-logger = logging.getLogger(__name__)
-
-
-class Modal(LLM):
- """Modal large language models.
-
- To use, you should have the ``modal-client`` python package installed.
-
- Any parameters that are valid to be passed to the call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Modal
- modal = Modal(endpoint_url="")
-
- """
-
- endpoint_url: str = ""
- """model endpoint to use"""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not
- explicitly specified."""
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"endpoint_url": self.endpoint_url},
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "modal"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to Modal endpoint."""
- params = self.model_kwargs or {}
- params = {**params, **kwargs}
- response = requests.post(
- url=self.endpoint_url,
- headers={
- "Content-Type": "application/json",
- },
- json={"prompt": prompt, **params},
- )
- try:
- if prompt in response.json()["prompt"]:
- response_json = response.json()
- except KeyError:
- raise ValueError("LangChain requires 'prompt' key in response.")
- text = response_json["prompt"]
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/mosaicml.py b/commune/modules/model/llm/mosaicml.py
deleted file mode 100644
index 718466178..000000000
--- a/commune/modules/model/llm/mosaicml.py
+++ /dev/null
@@ -1,188 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-INSTRUCTION_KEY = "### Instruction:"
-RESPONSE_KEY = "### Response:"
-INTRO_BLURB = (
- "Below is an instruction that describes a task. "
- "Write a response that appropriately completes the request."
-)
-PROMPT_FOR_GENERATION_FORMAT = """{intro}
-{instruction_key}
-{instruction}
-{response_key}
-""".format(
- intro=INTRO_BLURB,
- instruction_key=INSTRUCTION_KEY,
- instruction="{instruction}",
- response_key=RESPONSE_KEY,
-)
-
-
-class MosaicML(LLM):
- """MosaicML LLM service.
-
- To use, you should have the
- environment variable ``MOSAICML_API_TOKEN`` set with your API token, or pass
- it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import MosaicML
- endpoint_url = (
- "https://models.hosted-on.mosaicml.hosting/mpt-7b-instruct/v1/predict"
- )
- mosaic_llm = MosaicML(
- endpoint_url=endpoint_url,
- mosaicml_api_token="my-api-key"
- )
- """
-
- endpoint_url: str = (
- "https://models.hosted-on.mosaicml.hosting/mpt-7b-instruct/v1/predict"
- )
- """Endpoint URL to use."""
- inject_instruction_format: bool = False
- """Whether to inject the instruction format into the prompt."""
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
- retry_sleep: float = 1.0
- """How long to try sleeping for if a rate limit is encountered"""
-
- mosaicml_api_token: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- mosaicml_api_token = get_from_dict_or_env(
- values, "mosaicml_api_token", "MOSAICML_API_TOKEN"
- )
- values["mosaicml_api_token"] = mosaicml_api_token
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"endpoint_url": self.endpoint_url},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "mosaic"
-
- def _transform_prompt(self, prompt: str) -> str:
- """Transform prompt."""
- if self.inject_instruction_format:
- prompt = PROMPT_FOR_GENERATION_FORMAT.format(
- instruction=prompt,
- )
- return prompt
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- is_retry: bool = False,
- **kwargs: Any,
- ) -> str:
- """Call out to a MosaicML LLM inference endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = mosaic_llm("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
-
- prompt = self._transform_prompt(prompt)
-
- payload = {"inputs": [prompt]}
- payload.update(_model_kwargs)
- payload.update(kwargs)
-
- # HTTP headers for authorization
- headers = {
- "Authorization": f"{self.mosaicml_api_token}",
- "Content-Type": "application/json",
- }
-
- # send request
- try:
- response = requests.post(self.endpoint_url, headers=headers, json=payload)
- except requests.exceptions.RequestException as e:
- raise ValueError(f"Error raised by inference endpoint: {e}")
-
- try:
- if response.status_code == 429:
- if not is_retry:
- import time
-
- time.sleep(self.retry_sleep)
-
- return self._call(prompt, stop, run_manager, is_retry=True)
-
- raise ValueError(
- f"Error raised by inference API: rate limit exceeded.\nResponse: "
- f"{response.text}"
- )
-
- parsed_response = response.json()
-
- # The inference API has changed a couple of times, so we add some handling
- # to be robust to multiple response formats.
- if isinstance(parsed_response, dict):
- output_keys = ["data", "output", "outputs"]
- for key in output_keys:
- if key in parsed_response:
- output_item = parsed_response[key]
- break
- else:
- raise ValueError(
- f"No valid key ({', '.join(output_keys)}) in response:"
- f" {parsed_response}"
- )
- if isinstance(output_item, list):
- text = output_item[0]
- else:
- text = output_item
- else:
- raise ValueError(f"Unexpected response type: {parsed_response}")
-
- # Older versions of the API include the input in the output response
- if text.startswith(prompt):
- text = text[len(prompt) :]
-
- except requests.exceptions.JSONDecodeError as e:
- raise ValueError(
- f"Error raised by inference API: {e}.\nResponse: {response.text}"
- )
-
- # TODO: replace when MosaicML supports custom stop tokens natively
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/nlpcloud.py b/commune/modules/model/llm/nlpcloud.py
deleted file mode 100644
index d908e374e..000000000
--- a/commune/modules/model/llm/nlpcloud.py
+++ /dev/null
@@ -1,145 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class NLPCloud(LLM):
- """NLPCloud large language models.
-
- To use, you should have the ``nlpcloud`` python package installed, and the
- environment variable ``NLPCLOUD_API_KEY`` set with your API key.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import NLPCloud
- nlpcloud = NLPCloud(model="finetuned-gpt-neox-20b")
- """
-
- client: Any #: :meta private:
- model_name: str = "finetuned-gpt-neox-20b"
- """Model name to use."""
- gpu: bool = True
- """Whether to use a GPU or not"""
- lang: str = "en"
- """Language to use (multilingual addon)"""
- temperature: float = 0.7
- """What sampling temperature to use."""
- max_length: int = 256
- """The maximum number of tokens to generate in the completion."""
- length_no_input: bool = True
- """Whether min_length and max_length should include the length of the input."""
- remove_input: bool = True
- """Remove input text from API response"""
- remove_end_sequence: bool = True
- """Whether or not to remove the end sequence token."""
- bad_words: List[str] = []
- """List of tokens not allowed to be generated."""
- top_p: int = 1
- """Total probability mass of tokens to consider at each step."""
- top_k: int = 50
- """The number of highest probability tokens to keep for top-k filtering."""
- repetition_penalty: float = 1.0
- """Penalizes repeated tokens. 1.0 means no penalty."""
- num_beams: int = 1
- """Number of beams for beam search."""
- num_return_sequences: int = 1
- """How many completions to generate for each prompt."""
-
- nlpcloud_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- nlpcloud_api_key = get_from_dict_or_env(
- values, "nlpcloud_api_key", "NLPCLOUD_API_KEY"
- )
- try:
- import nlpcloud
-
- values["client"] = nlpcloud.Client(
- values["model_name"],
- nlpcloud_api_key,
- gpu=values["gpu"],
- lang=values["lang"],
- )
- except ImportError:
- raise ImportError(
- "Could not import nlpcloud python package. "
- "Please install it with `pip install nlpcloud`."
- )
- return values
-
- @property
- def _default_params(self) -> Mapping[str, Any]:
- """Get the default parameters for calling NLPCloud API."""
- return {
- "temperature": self.temperature,
- "max_length": self.max_length,
- "length_no_input": self.length_no_input,
- "remove_input": self.remove_input,
- "remove_end_sequence": self.remove_end_sequence,
- "bad_words": self.bad_words,
- "top_p": self.top_p,
- "top_k": self.top_k,
- "repetition_penalty": self.repetition_penalty,
- "num_beams": self.num_beams,
- "num_return_sequences": self.num_return_sequences,
- }
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_name": self.model_name},
- **{"gpu": self.gpu},
- **{"lang": self.lang},
- **self._default_params,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "nlpcloud"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to NLPCloud's create endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Not supported by this interface (pass in init method)
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = nlpcloud("Tell me a joke.")
- """
- if stop and len(stop) > 1:
- raise ValueError(
- "NLPCloud only supports a single stop sequence per generation."
- "Pass in a list of length 1."
- )
- elif stop and len(stop) == 1:
- end_sequence = stop[0]
- else:
- end_sequence = None
- params = {**self._default_params, **kwargs}
- response = self.client.generation(prompt, end_sequence=end_sequence, **params)
- return response["generated_text"]
diff --git a/commune/modules/model/llm/octoai_endpoint.py b/commune/modules/model/llm/octoai_endpoint.py
deleted file mode 100644
index 93bdb36ff..000000000
--- a/commune/modules/model/llm/octoai_endpoint.py
+++ /dev/null
@@ -1,120 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class OctoAIEndpoint(LLM):
- """OctoAI LLM Endpoints.
-
- OctoAIEndpoint is a class to interact with OctoAI
- Compute Service large language model endpoints.
-
- To use, you should have the ``octoai`` python package installed, and the
- environment variable ``OCTOAI_API_TOKEN`` set with your API token, or pass
- it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms.octoai_endpoint import OctoAIEndpoint
- OctoAIEndpoint(
- octoai_api_token="octoai-api-key",
- endpoint_url="https://mpt-7b-demo-kk0powt97tmb.octoai.cloud/generate",
- model_kwargs={
- "max_new_tokens": 200,
- "temperature": 0.75,
- "top_p": 0.95,
- "repetition_penalty": 1,
- "seed": None,
- "stop": [],
- },
- )
-
- """
-
- endpoint_url: Optional[str] = None
- """Endpoint URL to use."""
-
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
-
- octoai_api_token: Optional[str] = None
- """OCTOAI API Token"""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator(allow_reuse=True)
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- octoai_api_token = get_from_dict_or_env(
- values, "octoai_api_token", "OCTOAI_API_TOKEN"
- )
- values["endpoint_url"] = get_from_dict_or_env(
- values, "endpoint_url", "ENDPOINT_URL"
- )
-
- values["octoai_api_token"] = octoai_api_token
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"endpoint_url": self.endpoint_url},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "octoai_endpoint"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to OctoAI's inference endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- """
- _model_kwargs = self.model_kwargs or {}
-
- # Prepare the payload JSON
- parameter_payload = {"inputs": prompt, "parameters": _model_kwargs}
-
- try:
- # Initialize the OctoAI client
- from octoai import client
-
- octoai_client = client.Client(token=self.octoai_api_token)
-
- # Send the request using the OctoAI client
- resp_json = octoai_client.infer(self.endpoint_url, parameter_payload)
- text = resp_json["generated_text"]
-
- except Exception as e:
- # Handle any errors raised by the inference endpoint
- raise ValueError(f"Error raised by the inference endpoint: {e}") from e
-
- if stop is not None:
- # Apply stop tokens when making calls to OctoAI
- text = enforce_stop_tokens(text, stop)
-
- return text
diff --git a/commune/modules/model/llm/ollama.py b/commune/modules/model/llm/ollama.py
deleted file mode 100644
index 527bbcbc4..000000000
--- a/commune/modules/model/llm/ollama.py
+++ /dev/null
@@ -1,245 +0,0 @@
-import json
-from typing import Any, Dict, Iterator, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import BaseLLM
-from langchain.pydantic_v1 import Extra
-from langchain.schema import LLMResult
-from langchain.schema.language_model import BaseLanguageModel
-from langchain.schema.output import GenerationChunk
-
-
-def _stream_response_to_generation_chunk(
- stream_response: str,
-) -> GenerationChunk:
- """Convert a stream response to a generation chunk."""
- parsed_response = json.loads(stream_response)
- generation_info = parsed_response if parsed_response.get("done") is True else None
- return GenerationChunk(
- text=parsed_response.get("response", ""), generation_info=generation_info
- )
-
-
-class _OllamaCommon(BaseLanguageModel):
- base_url: str = "http://localhost:11434"
- """Base url the model is hosted under."""
-
- model: str = "llama2"
- """Model name to use."""
-
- mirostat: Optional[int]
- """Enable Mirostat sampling for controlling perplexity.
- (default: 0, 0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0)"""
-
- mirostat_eta: Optional[float]
- """Influences how quickly the algorithm responds to feedback
- from the generated text. A lower learning rate will result in
- slower adjustments, while a higher learning rate will make
- the algorithm more responsive. (Default: 0.1)"""
-
- mirostat_tau: Optional[float]
- """Controls the balance between coherence and diversity
- of the output. A lower value will result in more focused and
- coherent text. (Default: 5.0)"""
-
- num_ctx: Optional[int]
- """Sets the size of the context window used to generate the
- next token. (Default: 2048) """
-
- num_gpu: Optional[int]
- """The number of GPUs to use. On macOS it defaults to 1 to
- enable metal support, 0 to disable."""
-
- num_thread: Optional[int]
- """Sets the number of threads to use during computation.
- By default, Ollama will detect this for optimal performance.
- It is recommended to set this value to the number of physical
- CPU cores your system has (as opposed to the logical number of cores)."""
-
- repeat_last_n: Optional[int]
- """Sets how far back for the model to look back to prevent
- repetition. (Default: 64, 0 = disabled, -1 = num_ctx)"""
-
- repeat_penalty: Optional[float]
- """Sets how strongly to penalize repetitions. A higher value (e.g., 1.5)
- will penalize repetitions more strongly, while a lower value (e.g., 0.9)
- will be more lenient. (Default: 1.1)"""
-
- temperature: Optional[float]
- """The temperature of the model. Increasing the temperature will
- make the model answer more creatively. (Default: 0.8)"""
-
- stop: Optional[List[str]]
- """Sets the stop tokens to use."""
-
- tfs_z: Optional[float]
- """Tail free sampling is used to reduce the impact of less probable
- tokens from the output. A higher value (e.g., 2.0) will reduce the
- impact more, while a value of 1.0 disables this setting. (default: 1)"""
-
- top_k: Optional[int]
- """Reduces the probability of generating nonsense. A higher value (e.g. 100)
- will give more diverse answers, while a lower value (e.g. 10)
- will be more conservative. (Default: 40)"""
-
- top_p: Optional[int]
- """Works together with top-k. A higher value (e.g., 0.95) will lead
- to more diverse text, while a lower value (e.g., 0.5) will
- generate more focused and conservative text. (Default: 0.9)"""
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Ollama."""
- return {
- "model": self.model,
- "options": {
- "mirostat": self.mirostat,
- "mirostat_eta": self.mirostat_eta,
- "mirostat_tau": self.mirostat_tau,
- "num_ctx": self.num_ctx,
- "num_gpu": self.num_gpu,
- "num_thread": self.num_thread,
- "repeat_last_n": self.repeat_last_n,
- "repeat_penalty": self.repeat_penalty,
- "temperature": self.temperature,
- "stop": self.stop,
- "tfs_z": self.tfs_z,
- "top_k": self.top_k,
- "top_p": self.top_p,
- },
- }
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{"model": self.model}, **self._default_params}
-
- def _create_stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> Iterator[str]:
- if self.stop is not None and stop is not None:
- raise ValueError("`stop` found in both the input and default params.")
- elif self.stop is not None:
- stop = self.stop
- elif stop is None:
- stop = []
- params = {**self._default_params, "stop": stop, **kwargs}
- response = requests.post(
- url=f"{self.base_url}/api/generate/",
- headers={"Content-Type": "application/json"},
- json={"prompt": prompt, **params},
- stream=True,
- )
- response.encoding = "utf-8"
- if response.status_code != 200:
- optional_detail = response.json().get("error")
- raise ValueError(
- f"Ollama call failed with status code {response.status_code}."
- f" Details: {optional_detail}"
- )
- return response.iter_lines(decode_unicode=True)
-
- def _stream_with_aggregation(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- verbose: bool = False,
- **kwargs: Any,
- ) -> GenerationChunk:
- final_chunk: Optional[GenerationChunk] = None
- for stream_resp in self._create_stream(prompt, stop, **kwargs):
- if stream_resp:
- chunk = _stream_response_to_generation_chunk(stream_resp)
- if final_chunk is None:
- final_chunk = chunk
- else:
- final_chunk += chunk
- if run_manager:
- run_manager.on_llm_new_token(
- chunk.text,
- verbose=verbose,
- )
- if final_chunk is None:
- raise ValueError("No data received from Ollama stream.")
-
- return final_chunk
-
-
-class Ollama(BaseLLM, _OllamaCommon):
- """Ollama locally runs large language models.
-
- To use, follow the instructions at https://ollama.ai/.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Ollama
- ollama = Ollama(model="llama2")
- """
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "ollama-llm"
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call out to Ollama's generate endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = ollama("Tell me a joke.")
- """
- # TODO: add caching here.
- generations = []
- for prompt in prompts:
- final_chunk = super()._stream_with_aggregation(
- prompt,
- stop=stop,
- run_manager=run_manager,
- verbose=self.verbose,
- **kwargs,
- )
- generations.append([final_chunk])
- return LLMResult(generations=generations)
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- for stream_resp in self._create_stream(prompt, stop, **kwargs):
- if stream_resp:
- chunk = _stream_response_to_generation_chunk(stream_resp)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(
- chunk.text,
- verbose=self.verbose,
- )
diff --git a/commune/modules/model/llm/opaqueprompts.py b/commune/modules/model/llm/opaqueprompts.py
deleted file mode 100644
index af3ccc967..000000000
--- a/commune/modules/model/llm/opaqueprompts.py
+++ /dev/null
@@ -1,116 +0,0 @@
-import logging
-from typing import Any, Dict, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.schema.language_model import BaseLanguageModel
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class OpaquePrompts(LLM):
- """An LLM wrapper that uses OpaquePrompts to sanitize prompts.
-
- Wraps another LLM and sanitizes prompts before passing it to the LLM, then
- de-sanitizes the response.
-
- To use, you should have the ``opaqueprompts`` python package installed,
- and the environment variable ``OPAQUEPROMPTS_API_KEY`` set with
- your API key, or pass it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import OpaquePrompts
- from langchain.chat_models import ChatOpenAI
-
- op_llm = OpaquePrompts(base_llm=ChatOpenAI())
- """
-
- base_llm: BaseLanguageModel
- """The base LLM to use."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validates that the OpaquePrompts API key and the Python package exist."""
- try:
- import opaqueprompts as op
- except ImportError:
- raise ImportError(
- "Could not import the `opaqueprompts` Python package, "
- "please install it with `pip install opaqueprompts`."
- )
- if op.__package__ is None:
- raise ValueError(
- "Could not properly import `opaqueprompts`, "
- "opaqueprompts.__package__ is None."
- )
-
- api_key = get_from_dict_or_env(
- values, "opaqueprompts_api_key", "OPAQUEPROMPTS_API_KEY", default=""
- )
- if not api_key:
- raise ValueError(
- "Could not find OPAQUEPROMPTS_API_KEY in the environment. "
- "Please set it to your OpaquePrompts API key."
- "You can get it by creating an account on the OpaquePrompts website: "
- "https://opaqueprompts.opaque.co/ ."
- )
- return values
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call base LLM with sanitization before and de-sanitization after.
-
- Args:
- prompt: The prompt to pass into the model.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = op_llm("Tell me a joke.")
- """
- import opaqueprompts as op
-
- _run_manager = run_manager or CallbackManagerForLLMRun.get_noop_manager()
-
- # sanitize the prompt by replacing the sensitive information with a placeholder
- sanitize_response: op.SanitizeResponse = op.sanitize([prompt])
- sanitized_prompt_value_str = sanitize_response.sanitized_texts[0]
-
- # TODO: Add in callbacks once child runs for LLMs are supported by LangSmith.
- # call the LLM with the sanitized prompt and get the response
- llm_response = self.base_llm.predict(
- sanitized_prompt_value_str,
- stop=stop,
- )
-
- # desanitize the response by restoring the original sensitive information
- desanitize_response: op.DesanitizeResponse = op.desanitize(
- llm_response,
- secure_context=sanitize_response.secure_context,
- )
- return desanitize_response.desanitized_text
-
- @property
- def _llm_type(self) -> str:
- """Return type of LLM.
-
- This is an override of the base class method.
- """
- return "opaqueprompts"
diff --git a/commune/modules/model/llm/openai.py b/commune/modules/model/llm/openai.py
deleted file mode 100644
index 2ec199149..000000000
--- a/commune/modules/model/llm/openai.py
+++ /dev/null
@@ -1,951 +0,0 @@
-from __future__ import annotations
-
-import logging
-import sys
-import warnings
-from typing import (
- AbstractSet,
- Any,
- AsyncIterator,
- Callable,
- Collection,
- Dict,
- Iterator,
- List,
- Literal,
- Mapping,
- Optional,
- Set,
- Tuple,
- Union,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import BaseLLM, create_base_retry_decorator
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import Generation, LLMResult
-from langchain.schema.output import GenerationChunk
-from langchain.utils import get_from_dict_or_env, get_pydantic_field_names
-from langchain.utils.utils import build_extra_kwargs
-
-logger = logging.getLogger(__name__)
-
-
-def update_token_usage(
- keys: Set[str], response: Dict[str, Any], token_usage: Dict[str, Any]
-) -> None:
- """Update token usage."""
- _keys_to_use = keys.intersection(response["usage"])
- for _key in _keys_to_use:
- if _key not in token_usage:
- token_usage[_key] = response["usage"][_key]
- else:
- token_usage[_key] += response["usage"][_key]
-
-
-def _stream_response_to_generation_chunk(
- stream_response: Dict[str, Any],
-) -> GenerationChunk:
- """Convert a stream response to a generation chunk."""
- return GenerationChunk(
- text=stream_response["choices"][0]["text"],
- generation_info=dict(
- finish_reason=stream_response["choices"][0].get("finish_reason", None),
- logprobs=stream_response["choices"][0].get("logprobs", None),
- ),
- )
-
-
-def _update_response(response: Dict[str, Any], stream_response: Dict[str, Any]) -> None:
- """Update response from the stream response."""
- response["choices"][0]["text"] += stream_response["choices"][0]["text"]
- response["choices"][0]["finish_reason"] = stream_response["choices"][0].get(
- "finish_reason", None
- )
- response["choices"][0]["logprobs"] = stream_response["choices"][0]["logprobs"]
-
-
-def _streaming_response_template() -> Dict[str, Any]:
- return {
- "choices": [
- {
- "text": "",
- "finish_reason": None,
- "logprobs": None,
- }
- ]
- }
-
-
-def _create_retry_decorator(
- llm: Union[BaseOpenAI, OpenAIChat],
- run_manager: Optional[
- Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]
- ] = None,
-) -> Callable[[Any], Any]:
- import openai
-
- errors = [
- openai.error.Timeout,
- openai.error.APIError,
- openai.error.APIConnectionError,
- openai.error.RateLimitError,
- openai.error.ServiceUnavailableError,
- ]
- return create_base_retry_decorator(
- error_types=errors, max_retries=llm.max_retries, run_manager=run_manager
- )
-
-
-def completion_with_retry(
- llm: Union[BaseOpenAI, OpenAIChat],
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- def _completion_with_retry(**kwargs: Any) -> Any:
- return llm.client.create(**kwargs)
-
- return _completion_with_retry(**kwargs)
-
-
-async def acompletion_with_retry(
- llm: Union[BaseOpenAI, OpenAIChat],
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the async completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- async def _completion_with_retry(**kwargs: Any) -> Any:
- # Use OpenAI's async api https://github.com/openai/openai-python#async-api
- return await llm.client.acreate(**kwargs)
-
- return await _completion_with_retry(**kwargs)
-
-
-class BaseOpenAI(BaseLLM):
- """Base OpenAI large language model class."""
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"openai_api_key": "OPENAI_API_KEY"}
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- client: Any = None #: :meta private:
- model_name: str = Field(default="text-davinci-003", alias="model")
- """Model name to use."""
- temperature: float = 0.7
- """What sampling temperature to use."""
- max_tokens: int = 256
- """The maximum number of tokens to generate in the completion.
- -1 returns as many tokens as possible given the prompt and
- the models maximal context size."""
- top_p: float = 1
- """Total probability mass of tokens to consider at each step."""
- frequency_penalty: float = 0
- """Penalizes repeated tokens according to frequency."""
- presence_penalty: float = 0
- """Penalizes repeated tokens."""
- n: int = 1
- """How many completions to generate for each prompt."""
- best_of: int = 1
- """Generates best_of completions server-side and returns the "best"."""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not explicitly specified."""
- openai_api_key: Optional[str] = None
- openai_api_base: Optional[str] = None
- openai_organization: Optional[str] = None
- # to support explicit proxy for OpenAI
- openai_proxy: Optional[str] = None
- batch_size: int = 20
- """Batch size to use when passing multiple documents to generate."""
- request_timeout: Optional[Union[float, Tuple[float, float]]] = None
- """Timeout for requests to OpenAI completion API. Default is 600 seconds."""
- logit_bias: Optional[Dict[str, float]] = Field(default_factory=dict)
- """Adjust the probability of specific tokens being generated."""
- max_retries: int = 6
- """Maximum number of retries to make when generating."""
- streaming: bool = False
- """Whether to stream the results or not."""
- allowed_special: Union[Literal["all"], AbstractSet[str]] = set()
- """Set of special tokens that are allowed。"""
- disallowed_special: Union[Literal["all"], Collection[str]] = "all"
- """Set of special tokens that are not allowed。"""
- tiktoken_model_name: Optional[str] = None
- """The model name to pass to tiktoken when using this class.
- Tiktoken is used to count the number of tokens in documents to constrain
- them to be under a certain limit. By default, when set to None, this will
- be the same as the embedding model name. However, there are some cases
- where you may want to use this Embedding class with a model name not
- supported by tiktoken. This can include when using Azure embeddings or
- when using one of the many model providers that expose an OpenAI-like
- API but with different models. In those cases, in order to avoid erroring
- when tiktoken is called, you can specify a model name to use here."""
-
- def __new__(cls, **data: Any) -> Union[OpenAIChat, BaseOpenAI]: # type: ignore
- """Initialize the OpenAI object."""
- model_name = data.get("model_name", "")
- if (
- model_name.startswith("gpt-3.5-turbo") or model_name.startswith("gpt-4")
- ) and "-instruct" not in model_name:
- warnings.warn(
- "You are trying to use a chat model. This way of initializing it is "
- "no longer supported. Instead, please use: "
- "`from langchain.chat_models import ChatOpenAI`"
- )
- return OpenAIChat(**data)
- return super().__new__(cls)
-
- class Config:
- """Configuration for this pydantic object."""
-
- allow_population_by_field_name = True
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = get_pydantic_field_names(cls)
- extra = values.get("model_kwargs", {})
- values["model_kwargs"] = build_extra_kwargs(
- extra, values, all_required_field_names
- )
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- values["openai_api_key"] = get_from_dict_or_env(
- values, "openai_api_key", "OPENAI_API_KEY"
- )
- values["openai_api_base"] = get_from_dict_or_env(
- values,
- "openai_api_base",
- "OPENAI_API_BASE",
- default="",
- )
- values["openai_proxy"] = get_from_dict_or_env(
- values,
- "openai_proxy",
- "OPENAI_PROXY",
- default="",
- )
- values["openai_organization"] = get_from_dict_or_env(
- values,
- "openai_organization",
- "OPENAI_ORGANIZATION",
- default="",
- )
- try:
- import openai
-
- values["client"] = openai.Completion
- except ImportError:
- raise ImportError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`."
- )
- if values["streaming"] and values["n"] > 1:
- raise ValueError("Cannot stream results when n > 1.")
- if values["streaming"] and values["best_of"] > 1:
- raise ValueError("Cannot stream results when best_of > 1.")
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- normal_params = {
- "temperature": self.temperature,
- "max_tokens": self.max_tokens,
- "top_p": self.top_p,
- "frequency_penalty": self.frequency_penalty,
- "presence_penalty": self.presence_penalty,
- "n": self.n,
- "request_timeout": self.request_timeout,
- "logit_bias": self.logit_bias,
- }
-
- # Azure gpt-35-turbo doesn't support best_of
- # don't specify best_of if it is 1
- if self.best_of > 1:
- normal_params["best_of"] = self.best_of
-
- return {**normal_params, **self.model_kwargs}
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- params = {**self._invocation_params, **kwargs, "stream": True}
- self.get_sub_prompts(params, [prompt], stop) # this mutates params
- for stream_resp in completion_with_retry(
- self, prompt=prompt, run_manager=run_manager, **params
- ):
- chunk = _stream_response_to_generation_chunk(stream_resp)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(
- chunk.text,
- chunk=chunk,
- verbose=self.verbose,
- logprobs=chunk.generation_info["logprobs"]
- if chunk.generation_info
- else None,
- )
-
- async def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- params = {**self._invocation_params, **kwargs, "stream": True}
- self.get_sub_prompts(params, [prompt], stop) # this mutate params
- async for stream_resp in await acompletion_with_retry(
- self, prompt=prompt, run_manager=run_manager, **params
- ):
- chunk = _stream_response_to_generation_chunk(stream_resp)
- yield chunk
- if run_manager:
- await run_manager.on_llm_new_token(
- chunk.text,
- chunk=chunk,
- verbose=self.verbose,
- logprobs=chunk.generation_info["logprobs"]
- if chunk.generation_info
- else None,
- )
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call out to OpenAI's endpoint with k unique prompts.
-
- Args:
- prompts: The prompts to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The full LLM output.
-
- Example:
- .. code-block:: python
-
- response = openai.generate(["Tell me a joke."])
- """
- # TODO: write a unit test for this
- params = self._invocation_params
- params = {**params, **kwargs}
- sub_prompts = self.get_sub_prompts(params, prompts, stop)
- choices = []
- token_usage: Dict[str, int] = {}
- # Get the token usage from the response.
- # Includes prompt, completion, and total tokens used.
- _keys = {"completion_tokens", "prompt_tokens", "total_tokens"}
- for _prompts in sub_prompts:
- if self.streaming:
- if len(_prompts) > 1:
- raise ValueError("Cannot stream results with multiple prompts.")
-
- generation: Optional[GenerationChunk] = None
- for chunk in self._stream(_prompts[0], stop, run_manager, **kwargs):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- choices.append(
- {
- "text": generation.text,
- "finish_reason": generation.generation_info.get("finish_reason")
- if generation.generation_info
- else None,
- "logprobs": generation.generation_info.get("logprobs")
- if generation.generation_info
- else None,
- }
- )
- else:
- response = completion_with_retry(
- self, prompt=_prompts, run_manager=run_manager, **params
- )
- choices.extend(response["choices"])
- update_token_usage(_keys, response, token_usage)
- return self.create_llm_result(choices, prompts, token_usage)
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call out to OpenAI's endpoint async with k unique prompts."""
- params = self._invocation_params
- params = {**params, **kwargs}
- sub_prompts = self.get_sub_prompts(params, prompts, stop)
- choices = []
- token_usage: Dict[str, int] = {}
- # Get the token usage from the response.
- # Includes prompt, completion, and total tokens used.
- _keys = {"completion_tokens", "prompt_tokens", "total_tokens"}
- for _prompts in sub_prompts:
- if self.streaming:
- if len(_prompts) > 1:
- raise ValueError("Cannot stream results with multiple prompts.")
-
- generation: Optional[GenerationChunk] = None
- async for chunk in self._astream(
- _prompts[0], stop, run_manager, **kwargs
- ):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- choices.append(
- {
- "text": generation.text,
- "finish_reason": generation.generation_info.get("finish_reason")
- if generation.generation_info
- else None,
- "logprobs": generation.generation_info.get("logprobs")
- if generation.generation_info
- else None,
- }
- )
- else:
- response = await acompletion_with_retry(
- self, prompt=_prompts, run_manager=run_manager, **params
- )
- choices.extend(response["choices"])
- update_token_usage(_keys, response, token_usage)
- return self.create_llm_result(choices, prompts, token_usage)
-
- def get_sub_prompts(
- self,
- params: Dict[str, Any],
- prompts: List[str],
- stop: Optional[List[str]] = None,
- ) -> List[List[str]]:
- """Get the sub prompts for llm call."""
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
- params["stop"] = stop
- if params["max_tokens"] == -1:
- if len(prompts) != 1:
- raise ValueError(
- "max_tokens set to -1 not supported for multiple inputs."
- )
- params["max_tokens"] = self.max_tokens_for_prompt(prompts[0])
- sub_prompts = [
- prompts[i : i + self.batch_size]
- for i in range(0, len(prompts), self.batch_size)
- ]
- return sub_prompts
-
- def create_llm_result(
- self, choices: Any, prompts: List[str], token_usage: Dict[str, int]
- ) -> LLMResult:
- """Create the LLMResult from the choices and prompts."""
- generations = []
- for i, _ in enumerate(prompts):
- sub_choices = choices[i * self.n : (i + 1) * self.n]
- generations.append(
- [
- Generation(
- text=choice["text"],
- generation_info=dict(
- finish_reason=choice.get("finish_reason"),
- logprobs=choice.get("logprobs"),
- ),
- )
- for choice in sub_choices
- ]
- )
- llm_output = {"token_usage": token_usage, "model_name": self.model_name}
- return LLMResult(generations=generations, llm_output=llm_output)
-
- @property
- def _invocation_params(self) -> Dict[str, Any]:
- """Get the parameters used to invoke the model."""
- openai_creds: Dict[str, Any] = {
- "api_key": self.openai_api_key,
- "api_base": self.openai_api_base,
- "organization": self.openai_organization,
- }
- if self.openai_proxy:
- import openai
-
- openai.proxy = {"http": self.openai_proxy, "https": self.openai_proxy} # type: ignore[assignment] # noqa: E501
- return {**openai_creds, **self._default_params}
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_name": self.model_name}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "openai"
-
- def get_token_ids(self, text: str) -> List[int]:
- """Get the token IDs using the tiktoken package."""
- # tiktoken NOT supported for Python < 3.8
- if sys.version_info[1] < 8:
- return super().get_num_tokens(text)
- try:
- import tiktoken
- except ImportError:
- raise ImportError(
- "Could not import tiktoken python package. "
- "This is needed in order to calculate get_num_tokens. "
- "Please install it with `pip install tiktoken`."
- )
-
- model_name = self.tiktoken_model_name or self.model_name
- try:
- enc = tiktoken.encoding_for_model(model_name)
- except KeyError:
- logger.warning("Warning: model not found. Using cl100k_base encoding.")
- model = "cl100k_base"
- enc = tiktoken.get_encoding(model)
-
- return enc.encode(
- text,
- allowed_special=self.allowed_special,
- disallowed_special=self.disallowed_special,
- )
-
- @staticmethod
- def modelname_to_contextsize(modelname: str) -> int:
- """Calculate the maximum number of tokens possible to generate for a model.
-
- Args:
- modelname: The modelname we want to know the context size for.
-
- Returns:
- The maximum context size
-
- Example:
- .. code-block:: python
-
- max_tokens = openai.modelname_to_contextsize("text-davinci-003")
- """
- model_token_mapping = {
- "gpt-4": 8192,
- "gpt-4-0314": 8192,
- "gpt-4-0613": 8192,
- "gpt-4-32k": 32768,
- "gpt-4-32k-0314": 32768,
- "gpt-4-32k-0613": 32768,
- "gpt-3.5-turbo": 4096,
- "gpt-3.5-turbo-0301": 4096,
- "gpt-3.5-turbo-0613": 4096,
- "gpt-3.5-turbo-16k": 16385,
- "gpt-3.5-turbo-16k-0613": 16385,
- "gpt-3.5-turbo-instruct": 4096,
- "text-ada-001": 2049,
- "ada": 2049,
- "text-babbage-001": 2040,
- "babbage": 2049,
- "text-curie-001": 2049,
- "curie": 2049,
- "davinci": 2049,
- "text-davinci-003": 4097,
- "text-davinci-002": 4097,
- "code-davinci-002": 8001,
- "code-davinci-001": 8001,
- "code-cushman-002": 2048,
- "code-cushman-001": 2048,
- }
-
- # handling finetuned models
- if "ft-" in modelname:
- modelname = modelname.split(":")[0]
-
- context_size = model_token_mapping.get(modelname, None)
-
- if context_size is None:
- raise ValueError(
- f"Unknown model: {modelname}. Please provide a valid OpenAI model name."
- "Known models are: " + ", ".join(model_token_mapping.keys())
- )
-
- return context_size
-
- @property
- def max_context_size(self) -> int:
- """Get max context size for this model."""
- return self.modelname_to_contextsize(self.model_name)
-
- def max_tokens_for_prompt(self, prompt: str) -> int:
- """Calculate the maximum number of tokens possible to generate for a prompt.
-
- Args:
- prompt: The prompt to pass into the model.
-
- Returns:
- The maximum number of tokens to generate for a prompt.
-
- Example:
- .. code-block:: python
-
- max_tokens = openai.max_token_for_prompt("Tell me a joke.")
- """
- num_tokens = self.get_num_tokens(prompt)
- return self.max_context_size - num_tokens
-
-
-class OpenAI(BaseOpenAI):
- """OpenAI large language models.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``OPENAI_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import OpenAI
- openai = OpenAI(model_name="text-davinci-003")
- """
-
- @property
- def _invocation_params(self) -> Dict[str, Any]:
- return {**{"model": self.model_name}, **super()._invocation_params}
-
-
-class AzureOpenAI(BaseOpenAI):
- """Azure-specific OpenAI large language models.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``OPENAI_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import AzureOpenAI
- openai = AzureOpenAI(model_name="text-davinci-003")
- """
-
- deployment_name: str = ""
- """Deployment name to use."""
- openai_api_type: str = ""
- openai_api_version: str = ""
-
- @root_validator()
- def validate_azure_settings(cls, values: Dict) -> Dict:
- values["openai_api_version"] = get_from_dict_or_env(
- values,
- "openai_api_version",
- "OPENAI_API_VERSION",
- )
- values["openai_api_type"] = get_from_dict_or_env(
- values, "openai_api_type", "OPENAI_API_TYPE", "azure"
- )
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- return {
- **{"deployment_name": self.deployment_name},
- **super()._identifying_params,
- }
-
- @property
- def _invocation_params(self) -> Dict[str, Any]:
- openai_params = {
- "engine": self.deployment_name,
- "api_type": self.openai_api_type,
- "api_version": self.openai_api_version,
- }
- return {**openai_params, **super()._invocation_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "azure"
-
-
-class OpenAIChat(BaseLLM):
- """OpenAI Chat large language models.
-
- To use, you should have the ``openai`` python package installed, and the
- environment variable ``OPENAI_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the openai.create call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import OpenAIChat
- openaichat = OpenAIChat(model_name="gpt-3.5-turbo")
- """
-
- client: Any #: :meta private:
- model_name: str = "gpt-3.5-turbo"
- """Model name to use."""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not explicitly specified."""
- openai_api_key: Optional[str] = None
- openai_api_base: Optional[str] = None
- # to support explicit proxy for OpenAI
- openai_proxy: Optional[str] = None
- max_retries: int = 6
- """Maximum number of retries to make when generating."""
- prefix_messages: List = Field(default_factory=list)
- """Series of messages for Chat input."""
- streaming: bool = False
- """Whether to stream the results or not."""
- allowed_special: Union[Literal["all"], AbstractSet[str]] = set()
- """Set of special tokens that are allowed。"""
- disallowed_special: Union[Literal["all"], Collection[str]] = "all"
- """Set of special tokens that are not allowed。"""
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- openai_api_key = get_from_dict_or_env(
- values, "openai_api_key", "OPENAI_API_KEY"
- )
- openai_api_base = get_from_dict_or_env(
- values,
- "openai_api_base",
- "OPENAI_API_BASE",
- default="",
- )
- openai_proxy = get_from_dict_or_env(
- values,
- "openai_proxy",
- "OPENAI_PROXY",
- default="",
- )
- openai_organization = get_from_dict_or_env(
- values, "openai_organization", "OPENAI_ORGANIZATION", default=""
- )
- try:
- import openai
-
- openai.api_key = openai_api_key
- if openai_api_base:
- openai.api_base = openai_api_base
- if openai_organization:
- openai.organization = openai_organization
- if openai_proxy:
- openai.proxy = {"http": openai_proxy, "https": openai_proxy} # type: ignore[assignment] # noqa: E501
- except ImportError:
- raise ImportError(
- "Could not import openai python package. "
- "Please install it with `pip install openai`."
- )
- try:
- values["client"] = openai.ChatCompletion
- except AttributeError:
- raise ValueError(
- "`openai` has no `ChatCompletion` attribute, this is likely "
- "due to an old version of the openai package. Try upgrading it "
- "with `pip install --upgrade openai`."
- )
- warnings.warn(
- "You are trying to use a chat model. This way of initializing it is "
- "no longer supported. Instead, please use: "
- "`from langchain.chat_models import ChatOpenAI`"
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- return self.model_kwargs
-
- def _get_chat_params(
- self, prompts: List[str], stop: Optional[List[str]] = None
- ) -> Tuple:
- if len(prompts) > 1:
- raise ValueError(
- f"OpenAIChat currently only supports single prompt, got {prompts}"
- )
- messages = self.prefix_messages + [{"role": "user", "content": prompts[0]}]
- params: Dict[str, Any] = {**{"model": self.model_name}, **self._default_params}
- if stop is not None:
- if "stop" in params:
- raise ValueError("`stop` found in both the input and default params.")
- params["stop"] = stop
- if params.get("max_tokens") == -1:
- # for ChatGPT api, omitting max_tokens is equivalent to having no limit
- del params["max_tokens"]
- return messages, params
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- messages, params = self._get_chat_params([prompt], stop)
- params = {**params, **kwargs, "stream": True}
- for stream_resp in completion_with_retry(
- self, messages=messages, run_manager=run_manager, **params
- ):
- token = stream_resp["choices"][0]["delta"].get("content", "")
- chunk = GenerationChunk(text=token)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(token, chunk=chunk)
-
- async def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- messages, params = self._get_chat_params([prompt], stop)
- params = {**params, **kwargs, "stream": True}
- async for stream_resp in await acompletion_with_retry(
- self, messages=messages, run_manager=run_manager, **params
- ):
- token = stream_resp["choices"][0]["delta"].get("content", "")
- chunk = GenerationChunk(text=token)
- yield chunk
- if run_manager:
- await run_manager.on_llm_new_token(token, chunk=chunk)
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- if self.streaming:
- generation: Optional[GenerationChunk] = None
- for chunk in self._stream(prompts[0], stop, run_manager, **kwargs):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return LLMResult(generations=[[generation]])
-
- messages, params = self._get_chat_params(prompts, stop)
- params = {**params, **kwargs}
- full_response = completion_with_retry(
- self, messages=messages, run_manager=run_manager, **params
- )
- llm_output = {
- "token_usage": full_response["usage"],
- "model_name": self.model_name,
- }
- return LLMResult(
- generations=[
- [Generation(text=full_response["choices"][0]["message"]["content"])]
- ],
- llm_output=llm_output,
- )
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- if self.streaming:
- generation: Optional[GenerationChunk] = None
- async for chunk in self._astream(prompts[0], stop, run_manager, **kwargs):
- if generation is None:
- generation = chunk
- else:
- generation += chunk
- assert generation is not None
- return LLMResult(generations=[[generation]])
-
- messages, params = self._get_chat_params(prompts, stop)
- params = {**params, **kwargs}
- full_response = await acompletion_with_retry(
- self, messages=messages, run_manager=run_manager, **params
- )
- llm_output = {
- "token_usage": full_response["usage"],
- "model_name": self.model_name,
- }
- return LLMResult(
- generations=[
- [Generation(text=full_response["choices"][0]["message"]["content"])]
- ],
- llm_output=llm_output,
- )
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_name": self.model_name}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "openai-chat"
-
- def get_token_ids(self, text: str) -> List[int]:
- """Get the token IDs using the tiktoken package."""
- # tiktoken NOT supported for Python < 3.8
- if sys.version_info[1] < 8:
- return super().get_token_ids(text)
- try:
- import tiktoken
- except ImportError:
- raise ImportError(
- "Could not import tiktoken python package. "
- "This is needed in order to calculate get_num_tokens. "
- "Please install it with `pip install tiktoken`."
- )
-
- enc = tiktoken.encoding_for_model(self.model_name)
- return enc.encode(
- text,
- allowed_special=self.allowed_special,
- disallowed_special=self.disallowed_special,
- )
diff --git a/commune/modules/model/llm/openllm.py b/commune/modules/model/llm/openllm.py
deleted file mode 100644
index 4677d8b96..000000000
--- a/commune/modules/model/llm/openllm.py
+++ /dev/null
@@ -1,328 +0,0 @@
-from __future__ import annotations
-
-import copy
-import json
-import logging
-from typing import (
- TYPE_CHECKING,
- Any,
- Dict,
- List,
- Literal,
- Optional,
- TypedDict,
- Union,
- overload,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import PrivateAttr
-
-if TYPE_CHECKING:
- import openllm
-
-
-ServerType = Literal["http", "grpc"]
-
-
-class IdentifyingParams(TypedDict):
- """Parameters for identifying a model as a typed dict."""
-
- model_name: str
- model_id: Optional[str]
- server_url: Optional[str]
- server_type: Optional[ServerType]
- embedded: bool
- llm_kwargs: Dict[str, Any]
-
-
-logger = logging.getLogger(__name__)
-
-
-class OpenLLM(LLM):
- """OpenLLM, supporting both in-process model
- instance and remote OpenLLM servers.
-
- To use, you should have the openllm library installed:
-
- .. code-block:: bash
-
- pip install openllm
-
- Learn more at: https://github.com/bentoml/openllm
-
- Example running an LLM model locally managed by OpenLLM:
- .. code-block:: python
-
- from langchain.llms import OpenLLM
- llm = OpenLLM(
- model_name='flan-t5',
- model_id='google/flan-t5-large',
- )
- llm("What is the difference between a duck and a goose?")
-
- For all available supported models, you can run 'openllm models'.
-
- If you have a OpenLLM server running, you can also use it remotely:
- .. code-block:: python
-
- from langchain.llms import OpenLLM
- llm = OpenLLM(server_url='http://localhost:3000')
- llm("What is the difference between a duck and a goose?")
- """
-
- model_name: Optional[str] = None
- """Model name to use. See 'openllm models' for all available models."""
- model_id: Optional[str] = None
- """Model Id to use. If not provided, will use the default model for the model name.
- See 'openllm models' for all available model variants."""
- server_url: Optional[str] = None
- """Optional server URL that currently runs a LLMServer with 'openllm start'."""
- server_type: ServerType = "http"
- """Optional server type. Either 'http' or 'grpc'."""
- embedded: bool = True
- """Initialize this LLM instance in current process by default. Should
- only set to False when using in conjunction with BentoML Service."""
- llm_kwargs: Dict[str, Any]
- """Key word arguments to be passed to openllm.LLM"""
-
- _runner: Optional[openllm.LLMRunner] = PrivateAttr(default=None)
- _client: Union[
- openllm.client.HTTPClient, openllm.client.GrpcClient, None
- ] = PrivateAttr(default=None)
-
- class Config:
- extra = "forbid"
-
- @overload
- def __init__(
- self,
- model_name: Optional[str] = ...,
- *,
- model_id: Optional[str] = ...,
- embedded: Literal[True, False] = ...,
- **llm_kwargs: Any,
- ) -> None:
- ...
-
- @overload
- def __init__(
- self,
- *,
- server_url: str = ...,
- server_type: Literal["grpc", "http"] = ...,
- **llm_kwargs: Any,
- ) -> None:
- ...
-
- def __init__(
- self,
- model_name: Optional[str] = None,
- *,
- model_id: Optional[str] = None,
- server_url: Optional[str] = None,
- server_type: Literal["grpc", "http"] = "http",
- embedded: bool = True,
- **llm_kwargs: Any,
- ):
- try:
- import openllm
- except ImportError as e:
- raise ImportError(
- "Could not import openllm. Make sure to install it with "
- "'pip install openllm.'"
- ) from e
-
- llm_kwargs = llm_kwargs or {}
-
- if server_url is not None:
- logger.debug("'server_url' is provided, returning a openllm.Client")
- assert (
- model_id is None and model_name is None
- ), "'server_url' and {'model_id', 'model_name'} are mutually exclusive"
- client_cls = (
- openllm.client.HTTPClient
- if server_type == "http"
- else openllm.client.GrpcClient
- )
- client = client_cls(server_url)
-
- super().__init__(
- **{
- "server_url": server_url,
- "server_type": server_type,
- "llm_kwargs": llm_kwargs,
- }
- )
- self._runner = None # type: ignore
- self._client = client
- else:
- assert model_name is not None, "Must provide 'model_name' or 'server_url'"
- # since the LLM are relatively huge, we don't actually want to convert the
- # Runner with embedded when running the server. Instead, we will only set
- # the init_local here so that LangChain users can still use the LLM
- # in-process. Wrt to BentoML users, setting embedded=False is the expected
- # behaviour to invoke the runners remotely.
- # We need to also enable ensure_available to download and setup the model.
- runner = openllm.Runner(
- model_name=model_name,
- model_id=model_id,
- init_local=embedded,
- ensure_available=True,
- **llm_kwargs,
- )
- super().__init__(
- **{
- "model_name": model_name,
- "model_id": model_id,
- "embedded": embedded,
- "llm_kwargs": llm_kwargs,
- }
- )
- self._client = None # type: ignore
- self._runner = runner
-
- @property
- def runner(self) -> openllm.LLMRunner:
- """
- Get the underlying openllm.LLMRunner instance for integration with BentoML.
-
- Example:
- .. code-block:: python
-
- llm = OpenLLM(
- model_name='flan-t5',
- model_id='google/flan-t5-large',
- embedded=False,
- )
- tools = load_tools(["serpapi", "llm-math"], llm=llm)
- agent = initialize_agent(
- tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION
- )
- svc = bentoml.Service("langchain-openllm", runners=[llm.runner])
-
- @svc.api(input=Text(), output=Text())
- def chat(input_text: str):
- return agent.run(input_text)
- """
- if self._runner is None:
- raise ValueError("OpenLLM must be initialized locally with 'model_name'")
- return self._runner
-
- @property
- def _identifying_params(self) -> IdentifyingParams:
- """Get the identifying parameters."""
- if self._client is not None:
- self.llm_kwargs.update(self._client.configuration)
- model_name = self._client.model_name
- model_id = self._client.model_id
- else:
- if self._runner is None:
- raise ValueError("Runner must be initialized.")
- model_name = self.model_name
- model_id = self.model_id
- try:
- self.llm_kwargs.update(
- json.loads(self._runner.identifying_params["configuration"])
- )
- except (TypeError, json.JSONDecodeError):
- pass
- return IdentifyingParams(
- server_url=self.server_url,
- server_type=self.server_type,
- embedded=self.embedded,
- llm_kwargs=self.llm_kwargs,
- model_name=model_name,
- model_id=model_id,
- )
-
- @property
- def _llm_type(self) -> str:
- return "openllm_client" if self._client else "openllm"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: CallbackManagerForLLMRun | None = None,
- **kwargs: Any,
- ) -> str:
- try:
- import openllm
- except ImportError as e:
- raise ImportError(
- "Could not import openllm. Make sure to install it with "
- "'pip install openllm'."
- ) from e
-
- copied = copy.deepcopy(self.llm_kwargs)
- copied.update(kwargs)
- config = openllm.AutoConfig.for_model(
- self._identifying_params["model_name"], **copied
- )
- if self._client:
- res = self._client.query(prompt, **config.model_dump(flatten=True))
- else:
- assert self._runner is not None
- res = self._runner(prompt, **config.model_dump(flatten=True))
- if isinstance(res, dict) and "text" in res:
- return res["text"]
- elif isinstance(res, str):
- return res
- else:
- raise ValueError(
- "Expected result to be a dict with key 'text' or a string. "
- f"Received {res}"
- )
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- try:
- import openllm
- except ImportError as e:
- raise ImportError(
- "Could not import openllm. Make sure to install it with "
- "'pip install openllm'."
- ) from e
-
- copied = copy.deepcopy(self.llm_kwargs)
- copied.update(kwargs)
- config = openllm.AutoConfig.for_model(
- self._identifying_params["model_name"], **copied
- )
- if self._client:
- res = await self._client.acall(
- "generate", prompt, **config.model_dump(flatten=True)
- )
- else:
- assert self._runner is not None
- (
- prompt,
- generate_kwargs,
- postprocess_kwargs,
- ) = self._runner.llm.sanitize_parameters(prompt, **kwargs)
- generated_result = await self._runner.generate.async_run(
- prompt, **generate_kwargs
- )
- res = self._runner.llm.postprocess_generate(
- prompt, generated_result, **postprocess_kwargs
- )
-
- if isinstance(res, dict) and "text" in res:
- return res["text"]
- elif isinstance(res, str):
- return res
- else:
- raise ValueError(
- "Expected result to be a dict with key 'text' or a string. "
- f"Received {res}"
- )
diff --git a/commune/modules/model/llm/openlm.py b/commune/modules/model/llm/openlm.py
deleted file mode 100644
index 156add03e..000000000
--- a/commune/modules/model/llm/openlm.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from typing import Any, Dict
-
-from langchain.llms.openai import BaseOpenAI
-from langchain.pydantic_v1 import root_validator
-
-
-class OpenLM(BaseOpenAI):
- """OpenLM models."""
-
- @property
- def _invocation_params(self) -> Dict[str, Any]:
- return {**{"model": self.model_name}, **super()._invocation_params}
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- try:
- import openlm
-
- values["client"] = openlm.Completion
- except ImportError:
- raise ImportError(
- "Could not import openlm python package. "
- "Please install it with `pip install openlm`."
- )
- if values["streaming"]:
- raise ValueError("Streaming not supported with openlm")
- return values
diff --git a/commune/modules/model/llm/petals.py b/commune/modules/model/llm/petals.py
deleted file mode 100644
index 9499b6028..000000000
--- a/commune/modules/model/llm/petals.py
+++ /dev/null
@@ -1,152 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class Petals(LLM):
- """Petals Bloom models.
-
- To use, you should have the ``petals`` python package installed, and the
- environment variable ``HUGGINGFACE_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import petals
- petals = Petals()
-
- """
-
- client: Any
- """The client to use for the API calls."""
-
- tokenizer: Any
- """The tokenizer to use for the API calls."""
-
- model_name: str = "bigscience/bloom-petals"
- """The model to use."""
-
- temperature: float = 0.7
- """What sampling temperature to use"""
-
- max_new_tokens: int = 256
- """The maximum number of new tokens to generate in the completion."""
-
- top_p: float = 0.9
- """The cumulative probability for top-p sampling."""
-
- top_k: Optional[int] = None
- """The number of highest probability vocabulary tokens
- to keep for top-k-filtering."""
-
- do_sample: bool = True
- """Whether or not to use sampling; use greedy decoding otherwise."""
-
- max_length: Optional[int] = None
- """The maximum length of the sequence to be generated."""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call
- not explicitly specified."""
-
- huggingface_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""WARNING! {field_name} is not default parameter.
- {field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- huggingface_api_key = get_from_dict_or_env(
- values, "huggingface_api_key", "HUGGINGFACE_API_KEY"
- )
- try:
- from petals import AutoDistributedModelForCausalLM
- from transformers import AutoTokenizer
-
- model_name = values["model_name"]
- values["tokenizer"] = AutoTokenizer.from_pretrained(model_name)
- values["client"] = AutoDistributedModelForCausalLM.from_pretrained(
- model_name
- )
- values["huggingface_api_key"] = huggingface_api_key
-
- except ImportError:
- raise ValueError(
- "Could not import transformers or petals python package."
- "Please install with `pip install -U transformers petals`."
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Petals API."""
- normal_params = {
- "temperature": self.temperature,
- "max_new_tokens": self.max_new_tokens,
- "top_p": self.top_p,
- "top_k": self.top_k,
- "do_sample": self.do_sample,
- "max_length": self.max_length,
- }
- return {**normal_params, **self.model_kwargs}
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_name": self.model_name}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "petals"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the Petals API."""
- params = self._default_params
- params = {**params, **kwargs}
- inputs = self.tokenizer(prompt, return_tensors="pt")["input_ids"]
- outputs = self.client.generate(inputs, **params)
- text = self.tokenizer.decode(outputs[0])
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/pipelineai.py b/commune/modules/model/llm/pipelineai.py
deleted file mode 100644
index 248666e6f..000000000
--- a/commune/modules/model/llm/pipelineai.py
+++ /dev/null
@@ -1,114 +0,0 @@
-import logging
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import BaseModel, Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class PipelineAI(LLM, BaseModel):
- """PipelineAI large language models.
-
- To use, you should have the ``pipeline-ai`` python package installed,
- and the environment variable ``PIPELINE_API_KEY`` set with your API key.
-
- Any parameters that are valid to be passed to the call can be passed
- in, even if not explicitly saved on this class.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import PipelineAI
- pipeline = PipelineAI(pipeline_key="")
- """
-
- pipeline_key: str = ""
- """The id or tag of the target pipeline"""
-
- pipeline_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any pipeline parameters valid for `create` call not
- explicitly specified."""
-
- pipeline_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic config."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("pipeline_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to pipeline_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["pipeline_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- pipeline_api_key = get_from_dict_or_env(
- values, "pipeline_api_key", "PIPELINE_API_KEY"
- )
- values["pipeline_api_key"] = pipeline_api_key
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"pipeline_key": self.pipeline_key},
- **{"pipeline_kwargs": self.pipeline_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "pipeline_ai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to Pipeline Cloud endpoint."""
- try:
- from pipeline import PipelineCloud
- except ImportError:
- raise ImportError(
- "Could not import pipeline-ai python package. "
- "Please install it with `pip install pipeline-ai`."
- )
- client = PipelineCloud(token=self.pipeline_api_key)
- params = self.pipeline_kwargs or {}
- params = {**params, **kwargs}
-
- run = client.run_pipeline(self.pipeline_key, [prompt, params])
- try:
- text = run.result_preview[0][0]
- except AttributeError:
- raise AttributeError(
- f"A pipeline run should have a `result_preview` attribute."
- f"Run was: {run}"
- )
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the pipeline parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/predibase.py b/commune/modules/model/llm/predibase.py
deleted file mode 100644
index 98ab06937..000000000
--- a/commune/modules/model/llm/predibase.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field
-
-
-class Predibase(LLM):
- """Use your Predibase models with Langchain.
-
- To use, you should have the ``predibase`` python package installed,
- and have your Predibase API key.
- """
-
- model: str
- predibase_api_key: str
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
-
- @property
- def _llm_type(self) -> str:
- return "predibase"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any
- ) -> str:
- try:
- from predibase import PredibaseClient
-
- pc = PredibaseClient(token=self.predibase_api_key)
- except ImportError as e:
- raise ImportError(
- "Could not import Predibase Python package. "
- "Please install it with `pip install predibase`."
- ) from e
- except ValueError as e:
- raise ValueError("Your API key is not correct. Please try again") from e
- # load model and version
- results = pc.prompt(prompt, model_name=self.model)
- return results[0].response
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_kwargs": self.model_kwargs},
- }
diff --git a/commune/modules/model/llm/predictionguard.py b/commune/modules/model/llm/predictionguard.py
deleted file mode 100644
index 697738112..000000000
--- a/commune/modules/model/llm/predictionguard.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import logging
-from typing import Any, Dict, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class PredictionGuard(LLM):
- """Prediction Guard large language models.
-
- To use, you should have the ``predictionguard`` python package installed, and the
- environment variable ``PREDICTIONGUARD_TOKEN`` set with your access token, or pass
- it as a named parameter to the constructor. To use Prediction Guard's API along
- with OpenAI models, set the environment variable ``OPENAI_API_KEY`` with your
- OpenAI API key as well.
-
- Example:
- .. code-block:: python
-
- pgllm = PredictionGuard(model="MPT-7B-Instruct",
- token="my-access-token",
- output={
- "type": "boolean"
- })
- """
-
- client: Any #: :meta private:
- model: Optional[str] = "MPT-7B-Instruct"
- """Model name to use."""
-
- output: Optional[Dict[str, Any]] = None
- """The output type or structure for controlling the LLM output."""
-
- max_tokens: int = 256
- """Denotes the number of tokens to predict per generation."""
-
- temperature: float = 0.75
- """A non-negative float that tunes the degree of randomness in generation."""
-
- token: Optional[str] = None
- """Your Prediction Guard access token."""
-
- stop: Optional[List[str]] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that the access token and python package exists in environment."""
- token = get_from_dict_or_env(values, "token", "PREDICTIONGUARD_TOKEN")
- try:
- import predictionguard as pg
-
- values["client"] = pg.Client(token=token)
- except ImportError:
- raise ImportError(
- "Could not import predictionguard python package. "
- "Please install it with `pip install predictionguard`."
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling the Prediction Guard API."""
- return {
- "max_tokens": self.max_tokens,
- "temperature": self.temperature,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model": self.model}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "predictionguard"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Prediction Guard's model API.
- Args:
- prompt: The prompt to pass into the model.
- Returns:
- The string generated by the model.
- Example:
- .. code-block:: python
- response = pgllm("Tell me a joke.")
- """
- import predictionguard as pg
-
- params = self._default_params
- if self.stop is not None and stop is not None:
- raise ValueError("`stop` found in both the input and default params.")
- elif self.stop is not None:
- params["stop_sequences"] = self.stop
- else:
- params["stop_sequences"] = stop
-
- response = pg.Completion.create(
- model=self.model,
- prompt=prompt,
- output=self.output,
- temperature=params["temperature"],
- max_tokens=params["max_tokens"],
- **kwargs,
- )
- text = response["choices"][0]["text"]
-
- # If stop tokens are provided, Prediction Guard's endpoint returns them.
- # In order to make this consistent with other endpoints, we strip them.
- if stop is not None or self.stop is not None:
- text = enforce_stop_tokens(text, params["stop_sequences"])
-
- return text
diff --git a/commune/modules/model/llm/promptlayer_openai.py b/commune/modules/model/llm/promptlayer_openai.py
deleted file mode 100644
index 4e1089cc0..000000000
--- a/commune/modules/model/llm/promptlayer_openai.py
+++ /dev/null
@@ -1,227 +0,0 @@
-import datetime
-from typing import Any, List, Optional
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms import OpenAI, OpenAIChat
-from langchain.schema import LLMResult
-
-
-class PromptLayerOpenAI(OpenAI):
- """PromptLayer OpenAI large language models.
-
- To use, you should have the ``openai`` and ``promptlayer`` python
- package installed, and the environment variable ``OPENAI_API_KEY``
- and ``PROMPTLAYER_API_KEY`` set with your openAI API key and
- promptlayer key respectively.
-
- All parameters that can be passed to the OpenAI LLM can also
- be passed here. The PromptLayerOpenAI LLM adds two optional
-
- parameters:
- ``pl_tags``: List of strings to tag the request with.
- ``return_pl_id``: If True, the PromptLayer request ID will be
- returned in the ``generation_info`` field of the
- ``Generation`` object.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import PromptLayerOpenAI
- openai = PromptLayerOpenAI(model_name="text-davinci-003")
- """
-
- pl_tags: Optional[List[str]]
- return_pl_id: Optional[bool] = False
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call OpenAI generate and then call PromptLayer API to log the request."""
- from promptlayer.utils import get_api_key, promptlayer_api_request
-
- request_start_time = datetime.datetime.now().timestamp()
- generated_responses = super()._generate(prompts, stop, run_manager)
- request_end_time = datetime.datetime.now().timestamp()
- for i in range(len(prompts)):
- prompt = prompts[i]
- generation = generated_responses.generations[i][0]
- resp = {
- "text": generation.text,
- "llm_output": generated_responses.llm_output,
- }
- params = {**self._identifying_params, **kwargs}
- pl_request_id = promptlayer_api_request(
- "langchain.PromptLayerOpenAI",
- "langchain",
- [prompt],
- params,
- self.pl_tags,
- resp,
- request_start_time,
- request_end_time,
- get_api_key(),
- return_pl_id=self.return_pl_id,
- )
- if self.return_pl_id:
- if generation.generation_info is None or not isinstance(
- generation.generation_info, dict
- ):
- generation.generation_info = {}
- generation.generation_info["pl_request_id"] = pl_request_id
- return generated_responses
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- from promptlayer.utils import get_api_key, promptlayer_api_request_async
-
- request_start_time = datetime.datetime.now().timestamp()
- generated_responses = await super()._agenerate(prompts, stop, run_manager)
- request_end_time = datetime.datetime.now().timestamp()
- for i in range(len(prompts)):
- prompt = prompts[i]
- generation = generated_responses.generations[i][0]
- resp = {
- "text": generation.text,
- "llm_output": generated_responses.llm_output,
- }
- params = {**self._identifying_params, **kwargs}
- pl_request_id = await promptlayer_api_request_async(
- "langchain.PromptLayerOpenAI.async",
- "langchain",
- [prompt],
- params,
- self.pl_tags,
- resp,
- request_start_time,
- request_end_time,
- get_api_key(),
- return_pl_id=self.return_pl_id,
- )
- if self.return_pl_id:
- if generation.generation_info is None or not isinstance(
- generation.generation_info, dict
- ):
- generation.generation_info = {}
- generation.generation_info["pl_request_id"] = pl_request_id
- return generated_responses
-
-
-class PromptLayerOpenAIChat(OpenAIChat):
- """Wrapper around OpenAI large language models.
-
- To use, you should have the ``openai`` and ``promptlayer`` python
- package installed, and the environment variable ``OPENAI_API_KEY``
- and ``PROMPTLAYER_API_KEY`` set with your openAI API key and
- promptlayer key respectively.
-
- All parameters that can be passed to the OpenAIChat LLM can also
- be passed here. The PromptLayerOpenAIChat adds two optional
-
- parameters:
- ``pl_tags``: List of strings to tag the request with.
- ``return_pl_id``: If True, the PromptLayer request ID will be
- returned in the ``generation_info`` field of the
- ``Generation`` object.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import PromptLayerOpenAIChat
- openaichat = PromptLayerOpenAIChat(model_name="gpt-3.5-turbo")
- """
-
- pl_tags: Optional[List[str]]
- return_pl_id: Optional[bool] = False
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Call OpenAI generate and then call PromptLayer API to log the request."""
- from promptlayer.utils import get_api_key, promptlayer_api_request
-
- request_start_time = datetime.datetime.now().timestamp()
- generated_responses = super()._generate(prompts, stop, run_manager)
- request_end_time = datetime.datetime.now().timestamp()
- for i in range(len(prompts)):
- prompt = prompts[i]
- generation = generated_responses.generations[i][0]
- resp = {
- "text": generation.text,
- "llm_output": generated_responses.llm_output,
- }
- params = {**self._identifying_params, **kwargs}
- pl_request_id = promptlayer_api_request(
- "langchain.PromptLayerOpenAIChat",
- "langchain",
- [prompt],
- params,
- self.pl_tags,
- resp,
- request_start_time,
- request_end_time,
- get_api_key(),
- return_pl_id=self.return_pl_id,
- )
- if self.return_pl_id:
- if generation.generation_info is None or not isinstance(
- generation.generation_info, dict
- ):
- generation.generation_info = {}
- generation.generation_info["pl_request_id"] = pl_request_id
- return generated_responses
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- from promptlayer.utils import get_api_key, promptlayer_api_request_async
-
- request_start_time = datetime.datetime.now().timestamp()
- generated_responses = await super()._agenerate(prompts, stop, run_manager)
- request_end_time = datetime.datetime.now().timestamp()
- for i in range(len(prompts)):
- prompt = prompts[i]
- generation = generated_responses.generations[i][0]
- resp = {
- "text": generation.text,
- "llm_output": generated_responses.llm_output,
- }
- params = {**self._identifying_params, **kwargs}
- pl_request_id = await promptlayer_api_request_async(
- "langchain.PromptLayerOpenAIChat.async",
- "langchain",
- [prompt],
- params,
- self.pl_tags,
- resp,
- request_start_time,
- request_end_time,
- get_api_key(),
- return_pl_id=self.return_pl_id,
- )
- if self.return_pl_id:
- if generation.generation_info is None or not isinstance(
- generation.generation_info, dict
- ):
- generation.generation_info = {}
- generation.generation_info["pl_request_id"] = pl_request_id
- return generated_responses
diff --git a/commune/modules/model/llm/replicate.py b/commune/modules/model/llm/replicate.py
deleted file mode 100644
index 7a146070e..000000000
--- a/commune/modules/model/llm/replicate.py
+++ /dev/null
@@ -1,217 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.schema.output import GenerationChunk
-from langchain.utils import get_from_dict_or_env
-
-if TYPE_CHECKING:
- from replicate.prediction import Prediction
-
-logger = logging.getLogger(__name__)
-
-
-class Replicate(LLM):
- """Replicate models.
-
- To use, you should have the ``replicate`` python package installed,
- and the environment variable ``REPLICATE_API_TOKEN`` set with your API token.
- You can find your token here: https://replicate.com/account
-
- The model param is required, but any other model parameters can also
- be passed in with the format model_kwargs={model_param: value, ...}
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Replicate
-
- replicate = Replicate(
- model=(
- "stability-ai/stable-diffusion: "
- "27b93a2413e7f36cd83da926f3656280b2931564ff050bf9575f1fdf9bcd7478",
- ),
- model_kwargs={"image_dimensions": "512x512"}
- )
- """
-
- model: str
- model_kwargs: Dict[str, Any] = Field(default_factory=dict, alias="input")
- replicate_api_token: Optional[str] = None
- prompt_key: Optional[str] = None
- version_obj: Any = Field(default=None, exclude=True)
- """Optionally pass in the model version object during initialization to avoid
- having to make an extra API call to retrieve it during streaming. NOTE: not
- serializable, is excluded from serialization.
- """
-
- streaming: bool = False
- """Whether to stream the results."""
-
- stop: List[str] = Field(default_factory=list)
- """Stop sequences to early-terminate generation."""
-
- class Config:
- """Configuration for this pydantic config."""
-
- allow_population_by_field_name = True
- extra = Extra.forbid
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"replicate_api_token": "REPLICATE_API_TOKEN"}
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- input = values.pop("input", {})
- if input:
- logger.warning(
- "Init param `input` is deprecated, please use `model_kwargs` instead."
- )
- extra = {**values.pop("model_kwargs", {}), **input}
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- replicate_api_token = get_from_dict_or_env(
- values, "replicate_api_token", "REPLICATE_API_TOKEN"
- )
- values["replicate_api_token"] = replicate_api_token
- return values
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {
- "model": self.model,
- "model_kwargs": self.model_kwargs,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of model."""
- return "replicate"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call to replicate endpoint."""
- if self.streaming:
- completion: Optional[str] = None
- for chunk in self._stream(
- prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- if completion is None:
- completion = chunk.text
- else:
- completion += chunk.text
- else:
- prediction = self._create_prediction(prompt, **kwargs)
- prediction.wait()
- if prediction.status == "failed":
- raise RuntimeError(prediction.error)
- if isinstance(prediction.output, str):
- completion = prediction.output
- else:
- completion = "".join(prediction.output)
- assert completion is not None
- stop_conditions = stop or self.stop
- for s in stop_conditions:
- if s in completion:
- completion = completion[: completion.find(s)]
- return completion
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- prediction = self._create_prediction(prompt, **kwargs)
- stop_conditions = stop or self.stop
- stop_condition_reached = False
- current_completion: str = ""
- for output in prediction.output_iterator():
- current_completion += output
- # test for stop conditions, if specified
- for s in stop_conditions:
- if s in current_completion:
- prediction.cancel()
- stop_condition_reached = True
- # Potentially some tokens that should still be yielded before ending
- # stream.
- stop_index = max(output.find(s), 0)
- output = output[:stop_index]
- if not output:
- break
- if output:
- yield GenerationChunk(text=output)
- if run_manager:
- run_manager.on_llm_new_token(
- output,
- verbose=self.verbose,
- )
- if stop_condition_reached:
- break
-
- def _create_prediction(self, prompt: str, **kwargs: Any) -> Prediction:
- try:
- import replicate as replicate_python
- except ImportError:
- raise ImportError(
- "Could not import replicate python package. "
- "Please install it with `pip install replicate`."
- )
-
- # get the model and version
- if self.version_obj is None:
- model_str, version_str = self.model.split(":")
- model = replicate_python.models.get(model_str)
- self.version_obj = model.versions.get(version_str)
-
- if self.prompt_key is None:
- # sort through the openapi schema to get the name of the first input
- input_properties = sorted(
- self.version_obj.openapi_schema["components"]["schemas"]["Input"][
- "properties"
- ].items(),
- key=lambda item: item[1].get("x-order", 0),
- )
-
- self.prompt_key = input_properties[0][0]
-
- input_: Dict = {
- self.prompt_key: prompt,
- **self.model_kwargs,
- **kwargs,
- }
- return replicate_python.predictions.create(
- version=self.version_obj, input=input_
- )
diff --git a/commune/modules/model/llm/rwkv.py b/commune/modules/model/llm/rwkv.py
deleted file mode 100644
index 8072b2b91..000000000
--- a/commune/modules/model/llm/rwkv.py
+++ /dev/null
@@ -1,233 +0,0 @@
-"""RWKV models.
-
-Based on https://github.com/saharNooby/rwkv.cpp/blob/master/rwkv/chat_with_bot.py
- https://github.com/BlinkDL/ChatRWKV/blob/main/v2/chat.py
-"""
-from typing import Any, Dict, List, Mapping, Optional, Set
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import BaseModel, Extra, root_validator
-
-
-class RWKV(LLM, BaseModel):
- """RWKV language models.
-
- To use, you should have the ``rwkv`` python package installed, the
- pre-trained model file, and the model's config information.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import RWKV
- model = RWKV(model="./models/rwkv-3b-fp16.bin", strategy="cpu fp32")
-
- # Simplest invocation
- response = model("Once upon a time, ")
- """
-
- model: str
- """Path to the pre-trained RWKV model file."""
-
- tokens_path: str
- """Path to the RWKV tokens file."""
-
- strategy: str = "cpu fp32"
- """Token context window."""
-
- rwkv_verbose: bool = True
- """Print debug information."""
-
- temperature: float = 1.0
- """The temperature to use for sampling."""
-
- top_p: float = 0.5
- """The top-p value to use for sampling."""
-
- penalty_alpha_frequency: float = 0.4
- """Positive values penalize new tokens based on their existing frequency
- in the text so far, decreasing the model's likelihood to repeat the same
- line verbatim.."""
-
- penalty_alpha_presence: float = 0.4
- """Positive values penalize new tokens based on whether they appear
- in the text so far, increasing the model's likelihood to talk about
- new topics.."""
-
- CHUNK_LEN: int = 256
- """Batch size for prompt processing."""
-
- max_tokens_per_generation: int = 256
- """Maximum number of tokens to generate."""
-
- client: Any = None #: :meta private:
-
- tokenizer: Any = None #: :meta private:
-
- pipeline: Any = None #: :meta private:
-
- model_tokens: Any = None #: :meta private:
-
- model_state: Any = None #: :meta private:
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {
- "verbose": self.verbose,
- "top_p": self.top_p,
- "temperature": self.temperature,
- "penalty_alpha_frequency": self.penalty_alpha_frequency,
- "penalty_alpha_presence": self.penalty_alpha_presence,
- "CHUNK_LEN": self.CHUNK_LEN,
- "max_tokens_per_generation": self.max_tokens_per_generation,
- }
-
- @staticmethod
- def _rwkv_param_names() -> Set[str]:
- """Get the identifying parameters."""
- return {
- "verbose",
- }
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that the python package exists in the environment."""
- try:
- import tokenizers
- except ImportError:
- raise ImportError(
- "Could not import tokenizers python package. "
- "Please install it with `pip install tokenizers`."
- )
- try:
- from rwkv.model import RWKV as RWKVMODEL
- from rwkv.utils import PIPELINE
-
- values["tokenizer"] = tokenizers.Tokenizer.from_file(values["tokens_path"])
-
- rwkv_keys = cls._rwkv_param_names()
- model_kwargs = {k: v for k, v in values.items() if k in rwkv_keys}
- model_kwargs["verbose"] = values["rwkv_verbose"]
- values["client"] = RWKVMODEL(
- values["model"], strategy=values["strategy"], **model_kwargs
- )
- values["pipeline"] = PIPELINE(values["client"], values["tokens_path"])
-
- except ImportError:
- raise ImportError(
- "Could not import rwkv python package. "
- "Please install it with `pip install rwkv`."
- )
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- "model": self.model,
- **self._default_params,
- **{k: v for k, v in self.__dict__.items() if k in RWKV._rwkv_param_names()},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return the type of llm."""
- return "rwkv"
-
- def run_rnn(self, _tokens: List[str], newline_adj: int = 0) -> Any:
- AVOID_REPEAT_TOKENS = []
- AVOID_REPEAT = ",:?!"
- for i in AVOID_REPEAT:
- dd = self.pipeline.encode(i)
- assert len(dd) == 1
- AVOID_REPEAT_TOKENS += dd
-
- tokens = [int(x) for x in _tokens]
- self.model_tokens += tokens
-
- out: Any = None
-
- while len(tokens) > 0:
- out, self.model_state = self.client.forward(
- tokens[: self.CHUNK_LEN], self.model_state
- )
- tokens = tokens[self.CHUNK_LEN :]
- END_OF_LINE = 187
- out[END_OF_LINE] += newline_adj # adjust \n probability
-
- if self.model_tokens[-1] in AVOID_REPEAT_TOKENS:
- out[self.model_tokens[-1]] = -999999999
- return out
-
- def rwkv_generate(self, prompt: str) -> str:
- self.model_state = None
- self.model_tokens = []
- logits = self.run_rnn(self.tokenizer.encode(prompt).ids)
- begin = len(self.model_tokens)
- out_last = begin
-
- occurrence: Dict = {}
-
- decoded = ""
- for i in range(self.max_tokens_per_generation):
- for n in occurrence:
- logits[n] -= (
- self.penalty_alpha_presence
- + occurrence[n] * self.penalty_alpha_frequency
- )
- token = self.pipeline.sample_logits(
- logits, temperature=self.temperature, top_p=self.top_p
- )
-
- END_OF_TEXT = 0
- if token == END_OF_TEXT:
- break
- if token not in occurrence:
- occurrence[token] = 1
- else:
- occurrence[token] += 1
-
- logits = self.run_rnn([token])
- xxx = self.tokenizer.decode(self.model_tokens[out_last:])
- if "\ufffd" not in xxx: # avoid utf-8 display issues
- decoded += xxx
- out_last = begin + i + 1
- if i >= self.max_tokens_per_generation - 100:
- break
-
- return decoded
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- r"""RWKV generation
-
- Args:
- prompt: The prompt to pass into the model.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- prompt = "Once upon a time, "
- response = model(prompt, n_predict=55)
- """
- text = self.rwkv_generate(prompt)
-
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/sagemaker_endpoint.py b/commune/modules/model/llm/sagemaker_endpoint.py
deleted file mode 100644
index b38cbd40d..000000000
--- a/commune/modules/model/llm/sagemaker_endpoint.py
+++ /dev/null
@@ -1,285 +0,0 @@
-"""Sagemaker InvokeEndpoint API."""
-from abc import abstractmethod
-from typing import Any, Dict, Generic, List, Mapping, Optional, TypeVar, Union
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-
-INPUT_TYPE = TypeVar("INPUT_TYPE", bound=Union[str, List[str]])
-OUTPUT_TYPE = TypeVar("OUTPUT_TYPE", bound=Union[str, List[List[float]]])
-
-
-class ContentHandlerBase(Generic[INPUT_TYPE, OUTPUT_TYPE]):
- """A handler class to transform input from LLM to a
- format that SageMaker endpoint expects.
-
- Similarly, the class handles transforming output from the
- SageMaker endpoint to a format that LLM class expects.
- """
-
- """
- Example:
- .. code-block:: python
-
- class ContentHandler(ContentHandlerBase):
- content_type = "application/json"
- accepts = "application/json"
-
- def transform_input(self, prompt: str, model_kwargs: Dict) -> bytes:
- input_str = json.dumps({prompt: prompt, **model_kwargs})
- return input_str.encode('utf-8')
-
- def transform_output(self, output: bytes) -> str:
- response_json = json.loads(output.read().decode("utf-8"))
- return response_json[0]["generated_text"]
- """
-
- content_type: Optional[str] = "text/plain"
- """The MIME type of the input data passed to endpoint"""
-
- accepts: Optional[str] = "text/plain"
- """The MIME type of the response data returned from endpoint"""
-
- @abstractmethod
- def transform_input(self, prompt: INPUT_TYPE, model_kwargs: Dict) -> bytes:
- """Transforms the input to a format that model can accept
- as the request Body. Should return bytes or seekable file
- like object in the format specified in the content_type
- request header.
- """
-
- @abstractmethod
- def transform_output(self, output: bytes) -> OUTPUT_TYPE:
- """Transforms the output from the model to string that
- the LLM class expects.
- """
-
-
-class LLMContentHandler(ContentHandlerBase[str, str]):
- """Content handler for LLM class."""
-
-
-class SagemakerEndpoint(LLM):
- """Sagemaker Inference Endpoint models.
-
- To use, you must supply the endpoint name from your deployed
- Sagemaker model & the region where it is deployed.
-
- To authenticate, the AWS client uses the following methods to
- automatically load credentials:
- https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html
-
- If a specific credential profile should be used, you must pass
- the name of the profile from the ~/.aws/credentials file that is to be used.
-
- Make sure the credentials / roles used have the required policies to
- access the Sagemaker endpoint.
- See: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html
- """
-
- """
- Args:
-
- region_name: The aws region e.g., `us-west-2`.
- Fallsback to AWS_DEFAULT_REGION env variable
- or region specified in ~/.aws/config.
-
- credentials_profile_name: The name of the profile in the ~/.aws/credentials
- or ~/.aws/config files, which has either access keys or role information
- specified. If not specified, the default credential profile or, if on an
- EC2 instance, credentials from IMDS will be used.
-
- client: boto3 client for Sagemaker Endpoint
-
- content_handler: Implementation for model specific LLMContentHandler
-
-
- Example:
- .. code-block:: python
-
- from langchain.llms import SagemakerEndpoint
- endpoint_name = (
- "my-endpoint-name"
- )
- region_name = (
- "us-west-2"
- )
- credentials_profile_name = (
- "default"
- )
- se = SagemakerEndpoint(
- endpoint_name=endpoint_name,
- region_name=region_name,
- credentials_profile_name=credentials_profile_name
- )
-
- #Use with boto3 client
- client = boto3.client(
- "sagemaker-runtime",
- region_name=region_name
- )
-
- se = SagemakerEndpoint(
- endpoint_name=endpoint_name,
- client=client
- )
-
- """
- client: Any = None
- """Boto3 client for sagemaker runtime"""
-
- endpoint_name: str = ""
- """The name of the endpoint from the deployed Sagemaker model.
- Must be unique within an AWS Region."""
-
- region_name: str = ""
- """The aws region where the Sagemaker model is deployed, eg. `us-west-2`."""
-
- credentials_profile_name: Optional[str] = None
- """The name of the profile in the ~/.aws/credentials or ~/.aws/config files, which
- has either access keys or role information specified.
- If not specified, the default credential profile or, if on an EC2 instance,
- credentials from IMDS will be used.
- See: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html
- """
-
- content_handler: LLMContentHandler
- """The content handler class that provides an input and
- output transform functions to handle formats between LLM
- and the endpoint.
- """
-
- """
- Example:
- .. code-block:: python
-
- from langchain.llms.sagemaker_endpoint import LLMContentHandler
-
- class ContentHandler(LLMContentHandler):
- content_type = "application/json"
- accepts = "application/json"
-
- def transform_input(self, prompt: str, model_kwargs: Dict) -> bytes:
- input_str = json.dumps({prompt: prompt, **model_kwargs})
- return input_str.encode('utf-8')
-
- def transform_output(self, output: bytes) -> str:
- response_json = json.loads(output.read().decode("utf-8"))
- return response_json[0]["generated_text"]
- """
-
- model_kwargs: Optional[Dict] = None
- """Key word arguments to pass to the model."""
-
- endpoint_kwargs: Optional[Dict] = None
- """Optional attributes passed to the invoke_endpoint
- function. See `boto3`_. docs for more info.
- .. _boto3:
- """
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Dont do anything if client provided externally"""
- if values.get("client") is not None:
- return values
-
- """Validate that AWS credentials to and python package exists in environment."""
- try:
- import boto3
-
- try:
- if values["credentials_profile_name"] is not None:
- session = boto3.Session(
- profile_name=values["credentials_profile_name"]
- )
- else:
- # use default credentials
- session = boto3.Session()
-
- values["client"] = session.client(
- "sagemaker-runtime", region_name=values["region_name"]
- )
-
- except Exception as e:
- raise ValueError(
- "Could not load credentials to authenticate with AWS client. "
- "Please check that credentials in the specified "
- "profile name are valid."
- ) from e
-
- except ImportError:
- raise ImportError(
- "Could not import boto3 python package. "
- "Please install it with `pip install boto3`."
- )
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- **{"endpoint_name": self.endpoint_name},
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "sagemaker_endpoint"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Sagemaker inference endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = se("Tell me a joke.")
- """
- _model_kwargs = self.model_kwargs or {}
- _model_kwargs = {**_model_kwargs, **kwargs}
- _endpoint_kwargs = self.endpoint_kwargs or {}
-
- body = self.content_handler.transform_input(prompt, _model_kwargs)
- content_type = self.content_handler.content_type
- accepts = self.content_handler.accepts
-
- # send request
- try:
- response = self.client.invoke_endpoint(
- EndpointName=self.endpoint_name,
- Body=body,
- ContentType=content_type,
- Accept=accepts,
- **_endpoint_kwargs,
- )
- except Exception as e:
- raise ValueError(f"Error raised by inference endpoint: {e}")
-
- text = self.content_handler.transform_output(response["Body"])
- if stop is not None:
- # This is a bit hacky, but I can't figure out a better way to enforce
- # stop tokens when making calls to the sagemaker endpoint.
- text = enforce_stop_tokens(text, stop)
-
- return text
diff --git a/commune/modules/model/llm/self_hosted.py b/commune/modules/model/llm/self_hosted.py
deleted file mode 100644
index b43ce822e..000000000
--- a/commune/modules/model/llm/self_hosted.py
+++ /dev/null
@@ -1,219 +0,0 @@
-import importlib.util
-import logging
-import pickle
-from typing import Any, Callable, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra
-
-logger = logging.getLogger(__name__)
-
-
-def _generate_text(
- pipeline: Any,
- prompt: str,
- *args: Any,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
-) -> str:
- """Inference function to send to the remote hardware.
-
- Accepts a pipeline callable (or, more likely,
- a key pointing to the model on the cluster's object store)
- and returns text predictions for each document
- in the batch.
- """
- text = pipeline(prompt, *args, **kwargs)
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
-
-
-def _send_pipeline_to_device(pipeline: Any, device: int) -> Any:
- """Send a pipeline to a device on the cluster."""
- if isinstance(pipeline, str):
- with open(pipeline, "rb") as f:
- pipeline = pickle.load(f)
-
- if importlib.util.find_spec("torch") is not None:
- import torch
-
- cuda_device_count = torch.cuda.device_count()
- if device < -1 or (device >= cuda_device_count):
- raise ValueError(
- f"Got device=={device}, "
- f"device is required to be within [-1, {cuda_device_count})"
- )
- if device < 0 and cuda_device_count > 0:
- logger.warning(
- "Device has %d GPUs available. "
- "Provide device={deviceId} to `from_model_id` to use available"
- "GPUs for execution. deviceId is -1 for CPU and "
- "can be a positive integer associated with CUDA device id.",
- cuda_device_count,
- )
-
- pipeline.device = torch.device(device)
- pipeline.model = pipeline.model.to(pipeline.device)
- return pipeline
-
-
-class SelfHostedPipeline(LLM):
- """Model inference on self-hosted remote hardware.
-
- Supported hardware includes auto-launched instances on AWS, GCP, Azure,
- and Lambda, as well as servers specified
- by IP address and SSH credentials (such as on-prem, or another
- cloud like Paperspace, Coreweave, etc.).
-
- To use, you should have the ``runhouse`` python package installed.
-
- Example for custom pipeline and inference functions:
- .. code-block:: python
-
- from langchain.llms import SelfHostedPipeline
- from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
- import runhouse as rh
-
- def load_pipeline():
- tokenizer = AutoTokenizer.from_pretrained("gpt2")
- model = AutoModelForCausalLM.from_pretrained("gpt2")
- return pipeline(
- "text-generation", model=model, tokenizer=tokenizer,
- max_new_tokens=10
- )
- def inference_fn(pipeline, prompt, stop = None):
- return pipeline(prompt)[0]["generated_text"]
-
- gpu = rh.cluster(name="rh-a10x", instance_type="A100:1")
- llm = SelfHostedPipeline(
- model_load_fn=load_pipeline,
- hardware=gpu,
- model_reqs=model_reqs, inference_fn=inference_fn
- )
- Example for <2GB model (can be serialized and sent directly to the server):
- .. code-block:: python
-
- from langchain.llms import SelfHostedPipeline
- import runhouse as rh
- gpu = rh.cluster(name="rh-a10x", instance_type="A100:1")
- my_model = ...
- llm = SelfHostedPipeline.from_pipeline(
- pipeline=my_model,
- hardware=gpu,
- model_reqs=["./", "torch", "transformers"],
- )
- Example passing model path for larger models:
- .. code-block:: python
-
- from langchain.llms import SelfHostedPipeline
- import runhouse as rh
- import pickle
- from transformers import pipeline
-
- generator = pipeline(model="gpt2")
- rh.blob(pickle.dumps(generator), path="models/pipeline.pkl"
- ).save().to(gpu, path="models")
- llm = SelfHostedPipeline.from_pipeline(
- pipeline="models/pipeline.pkl",
- hardware=gpu,
- model_reqs=["./", "torch", "transformers"],
- )
- """
-
- pipeline_ref: Any #: :meta private:
- client: Any #: :meta private:
- inference_fn: Callable = _generate_text #: :meta private:
- """Inference function to send to the remote hardware."""
- hardware: Any
- """Remote hardware to send the inference function to."""
- model_load_fn: Callable
- """Function to load the model remotely on the server."""
- load_fn_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model load function."""
- model_reqs: List[str] = ["./", "torch"]
- """Requirements to install on hardware to inference the model."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- def __init__(self, **kwargs: Any):
- """Init the pipeline with an auxiliary function.
-
- The load function must be in global scope to be imported
- and run on the server, i.e. in a module and not a REPL or closure.
- Then, initialize the remote inference function.
- """
- super().__init__(**kwargs)
- try:
- import runhouse as rh
-
- except ImportError:
- raise ImportError(
- "Could not import runhouse python package. "
- "Please install it with `pip install runhouse`."
- )
-
- remote_load_fn = rh.function(fn=self.model_load_fn).to(
- self.hardware, reqs=self.model_reqs
- )
- _load_fn_kwargs = self.load_fn_kwargs or {}
- self.pipeline_ref = remote_load_fn.remote(**_load_fn_kwargs)
-
- self.client = rh.function(fn=self.inference_fn).to(
- self.hardware, reqs=self.model_reqs
- )
-
- @classmethod
- def from_pipeline(
- cls,
- pipeline: Any,
- hardware: Any,
- model_reqs: Optional[List[str]] = None,
- device: int = 0,
- **kwargs: Any,
- ) -> LLM:
- """Init the SelfHostedPipeline from a pipeline object or string."""
- if not isinstance(pipeline, str):
- logger.warning(
- "Serializing pipeline to send to remote hardware. "
- "Note, it can be quite slow"
- "to serialize and send large models with each execution. "
- "Consider sending the pipeline"
- "to the cluster and passing the path to the pipeline instead."
- )
-
- load_fn_kwargs = {"pipeline": pipeline, "device": device}
- return cls(
- load_fn_kwargs=load_fn_kwargs,
- model_load_fn=_send_pipeline_to_device,
- hardware=hardware,
- model_reqs=["transformers", "torch"] + (model_reqs or []),
- **kwargs,
- )
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"hardware": self.hardware},
- }
-
- @property
- def _llm_type(self) -> str:
- return "self_hosted_llm"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- return self.client(
- pipeline=self.pipeline_ref, prompt=prompt, stop=stop, **kwargs
- )
diff --git a/commune/modules/model/llm/self_hosted_hugging_face.py b/commune/modules/model/llm/self_hosted_hugging_face.py
deleted file mode 100644
index 0b590cf51..000000000
--- a/commune/modules/model/llm/self_hosted_hugging_face.py
+++ /dev/null
@@ -1,212 +0,0 @@
-import importlib.util
-import logging
-from typing import Any, Callable, List, Mapping, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.self_hosted import SelfHostedPipeline
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra
-
-DEFAULT_MODEL_ID = "gpt2"
-DEFAULT_TASK = "text-generation"
-VALID_TASKS = ("text2text-generation", "text-generation", "summarization")
-
-logger = logging.getLogger(__name__)
-
-
-def _generate_text(
- pipeline: Any,
- prompt: str,
- *args: Any,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
-) -> str:
- """Inference function to send to the remote hardware.
-
- Accepts a Hugging Face pipeline (or more likely,
- a key pointing to such a pipeline on the cluster's object store)
- and returns generated text.
- """
- response = pipeline(prompt, *args, **kwargs)
- if pipeline.task == "text-generation":
- # Text generation return includes the starter text.
- text = response[0]["generated_text"][len(prompt) :]
- elif pipeline.task == "text2text-generation":
- text = response[0]["generated_text"]
- elif pipeline.task == "summarization":
- text = response[0]["summary_text"]
- else:
- raise ValueError(
- f"Got invalid task {pipeline.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
-
-
-def _load_transformer(
- model_id: str = DEFAULT_MODEL_ID,
- task: str = DEFAULT_TASK,
- device: int = 0,
- model_kwargs: Optional[dict] = None,
-) -> Any:
- """Inference function to send to the remote hardware.
-
- Accepts a huggingface model_id and returns a pipeline for the task.
- """
- from transformers import AutoModelForCausalLM, AutoModelForSeq2SeqLM, AutoTokenizer
- from transformers import pipeline as hf_pipeline
-
- _model_kwargs = model_kwargs or {}
- tokenizer = AutoTokenizer.from_pretrained(model_id, **_model_kwargs)
-
- try:
- if task == "text-generation":
- model = AutoModelForCausalLM.from_pretrained(model_id, **_model_kwargs)
- elif task in ("text2text-generation", "summarization"):
- model = AutoModelForSeq2SeqLM.from_pretrained(model_id, **_model_kwargs)
- else:
- raise ValueError(
- f"Got invalid task {task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- except ImportError as e:
- raise ValueError(
- f"Could not load the {task} model due to missing dependencies."
- ) from e
-
- if importlib.util.find_spec("torch") is not None:
- import torch
-
- cuda_device_count = torch.cuda.device_count()
- if device < -1 or (device >= cuda_device_count):
- raise ValueError(
- f"Got device=={device}, "
- f"device is required to be within [-1, {cuda_device_count})"
- )
- if device < 0 and cuda_device_count > 0:
- logger.warning(
- "Device has %d GPUs available. "
- "Provide device={deviceId} to `from_model_id` to use available"
- "GPUs for execution. deviceId is -1 for CPU and "
- "can be a positive integer associated with CUDA device id.",
- cuda_device_count,
- )
-
- pipeline = hf_pipeline(
- task=task,
- model=model,
- tokenizer=tokenizer,
- device=device,
- model_kwargs=_model_kwargs,
- )
- if pipeline.task not in VALID_TASKS:
- raise ValueError(
- f"Got invalid task {pipeline.task}, "
- f"currently only {VALID_TASKS} are supported"
- )
- return pipeline
-
-
-class SelfHostedHuggingFaceLLM(SelfHostedPipeline):
- """HuggingFace Pipeline API to run on self-hosted remote hardware.
-
- Supported hardware includes auto-launched instances on AWS, GCP, Azure,
- and Lambda, as well as servers specified
- by IP address and SSH credentials (such as on-prem, or another cloud
- like Paperspace, Coreweave, etc.).
-
- To use, you should have the ``runhouse`` python package installed.
-
- Only supports `text-generation`, `text2text-generation` and `summarization` for now.
-
- Example using from_model_id:
- .. code-block:: python
-
- from langchain.llms import SelfHostedHuggingFaceLLM
- import runhouse as rh
- gpu = rh.cluster(name="rh-a10x", instance_type="A100:1")
- hf = SelfHostedHuggingFaceLLM(
- model_id="google/flan-t5-large", task="text2text-generation",
- hardware=gpu
- )
- Example passing fn that generates a pipeline (bc the pipeline is not serializable):
- .. code-block:: python
-
- from langchain.llms import SelfHostedHuggingFaceLLM
- from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
- import runhouse as rh
-
- def get_pipeline():
- model_id = "gpt2"
- tokenizer = AutoTokenizer.from_pretrained(model_id)
- model = AutoModelForCausalLM.from_pretrained(model_id)
- pipe = pipeline(
- "text-generation", model=model, tokenizer=tokenizer
- )
- return pipe
- hf = SelfHostedHuggingFaceLLM(
- model_load_fn=get_pipeline, model_id="gpt2", hardware=gpu)
- """
-
- model_id: str = DEFAULT_MODEL_ID
- """Hugging Face model_id to load the model."""
- task: str = DEFAULT_TASK
- """Hugging Face task ("text-generation", "text2text-generation" or
- "summarization")."""
- device: int = 0
- """Device to use for inference. -1 for CPU, 0 for GPU, 1 for second GPU, etc."""
- model_kwargs: Optional[dict] = None
- """Key word arguments to pass to the model."""
- hardware: Any
- """Remote hardware to send the inference function to."""
- model_reqs: List[str] = ["./", "transformers", "torch"]
- """Requirements to install on hardware to inference the model."""
- model_load_fn: Callable = _load_transformer
- """Function to load the model remotely on the server."""
- inference_fn: Callable = _generate_text #: :meta private:
- """Inference function to send to the remote hardware."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- def __init__(self, **kwargs: Any):
- """Construct the pipeline remotely using an auxiliary function.
-
- The load function needs to be importable to be imported
- and run on the server, i.e. in a module and not a REPL or closure.
- Then, initialize the remote inference function.
- """
- load_fn_kwargs = {
- "model_id": kwargs.get("model_id", DEFAULT_MODEL_ID),
- "task": kwargs.get("task", DEFAULT_TASK),
- "device": kwargs.get("device", 0),
- "model_kwargs": kwargs.get("model_kwargs", None),
- }
- super().__init__(load_fn_kwargs=load_fn_kwargs, **kwargs)
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_id": self.model_id},
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- return "selfhosted_huggingface_pipeline"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- return self.client(
- pipeline=self.pipeline_ref, prompt=prompt, stop=stop, **kwargs
- )
diff --git a/commune/modules/model/llm/stochasticai.py b/commune/modules/model/llm/stochasticai.py
deleted file mode 100644
index 2afe7d695..000000000
--- a/commune/modules/model/llm/stochasticai.py
+++ /dev/null
@@ -1,137 +0,0 @@
-import logging
-import time
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, Field, root_validator
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-class StochasticAI(LLM):
- """StochasticAI large language models.
-
- To use, you should have the environment variable ``STOCHASTICAI_API_KEY``
- set with your API key.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import StochasticAI
- stochasticai = StochasticAI(api_url="")
- """
-
- api_url: str = ""
- """Model name to use."""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `create` call not
- explicitly specified."""
-
- stochasticai_api_key: Optional[str] = None
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = {field.alias for field in cls.__fields__.values()}
-
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name not in all_required_field_names:
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- logger.warning(
- f"""{field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
- values["model_kwargs"] = extra
- return values
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key exists in environment."""
- stochasticai_api_key = get_from_dict_or_env(
- values, "stochasticai_api_key", "STOCHASTICAI_API_KEY"
- )
- values["stochasticai_api_key"] = stochasticai_api_key
- return values
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"endpoint_url": self.api_url},
- **{"model_kwargs": self.model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "stochasticai"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to StochasticAI's complete endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = StochasticAI("Tell me a joke.")
- """
- params = self.model_kwargs or {}
- params = {**params, **kwargs}
- response_post = requests.post(
- url=self.api_url,
- json={"prompt": prompt, "params": params},
- headers={
- "apiKey": f"{self.stochasticai_api_key}",
- "Accept": "application/json",
- "Content-Type": "application/json",
- },
- )
- response_post.raise_for_status()
- response_post_json = response_post.json()
- completed = False
- while not completed:
- response_get = requests.get(
- url=response_post_json["data"]["responseUrl"],
- headers={
- "apiKey": f"{self.stochasticai_api_key}",
- "Accept": "application/json",
- "Content-Type": "application/json",
- },
- )
- response_get.raise_for_status()
- response_get_json = response_get.json()["data"]
- text = response_get_json.get("completion")
- completed = text is not None
- time.sleep(0.5)
- text = text[0]
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/symblai_nebula.py b/commune/modules/model/llm/symblai_nebula.py
deleted file mode 100644
index 8d33e1a42..000000000
--- a/commune/modules/model/llm/symblai_nebula.py
+++ /dev/null
@@ -1,243 +0,0 @@
-import json
-import logging
-from typing import Any, Callable, Dict, List, Mapping, Optional
-
-import requests
-from requests import ConnectTimeout, ReadTimeout, RequestException
-from tenacity import (
- before_sleep_log,
- retry,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-DEFAULT_NEBULA_SERVICE_URL = "https://api-nebula.symbl.ai"
-DEFAULT_NEBULA_SERVICE_PATH = "/v1/model/generate"
-
-logger = logging.getLogger(__name__)
-
-
-class Nebula(LLM):
- """Nebula Service models.
-
- To use, you should have the environment variable ``NEBULA_SERVICE_URL``,
- ``NEBULA_SERVICE_PATH`` and ``NEBULA_API_KEY`` set with your Nebula
- Service, or pass it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Nebula
-
- nebula = Nebula(
- nebula_service_url="NEBULA_SERVICE_URL",
- nebula_service_path="NEBULA_SERVICE_PATH",
- nebula_api_key="NEBULA_API_KEY",
- )
- """ # noqa: E501
-
- """Key/value arguments to pass to the model. Reserved for future use"""
- model_kwargs: Optional[dict] = None
-
- """Optional"""
-
- nebula_service_url: Optional[str] = None
- nebula_service_path: Optional[str] = None
- nebula_api_key: Optional[str] = None
- model: Optional[str] = None
- max_new_tokens: Optional[int] = 128
- temperature: Optional[float] = 0.6
- top_p: Optional[float] = 0.95
- repetition_penalty: Optional[float] = 1.0
- top_k: Optional[int] = 0
- penalty_alpha: Optional[float] = 0.0
- stop_sequences: Optional[List[str]] = None
- max_retries: Optional[int] = 10
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- nebula_service_url = get_from_dict_or_env(
- values,
- "nebula_service_url",
- "NEBULA_SERVICE_URL",
- DEFAULT_NEBULA_SERVICE_URL,
- )
- nebula_service_path = get_from_dict_or_env(
- values,
- "nebula_service_path",
- "NEBULA_SERVICE_PATH",
- DEFAULT_NEBULA_SERVICE_PATH,
- )
- nebula_api_key = get_from_dict_or_env(
- values, "nebula_api_key", "NEBULA_API_KEY", None
- )
-
- if nebula_service_url.endswith("/"):
- nebula_service_url = nebula_service_url[:-1]
- if not nebula_service_path.startswith("/"):
- nebula_service_path = "/" + nebula_service_path
-
- values["nebula_service_url"] = nebula_service_url
- values["nebula_service_path"] = nebula_service_path
- values["nebula_api_key"] = nebula_api_key
-
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Cohere API."""
- return {
- "max_new_tokens": self.max_new_tokens,
- "temperature": self.temperature,
- "top_k": self.top_k,
- "top_p": self.top_p,
- "repetition_penalty": self.repetition_penalty,
- "penalty_alpha": self.penalty_alpha,
- }
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- _model_kwargs = self.model_kwargs or {}
- return {
- "nebula_service_url": self.nebula_service_url,
- "nebula_service_path": self.nebula_service_path,
- **{"model_kwargs": _model_kwargs},
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "nebula"
-
- def _invocation_params(
- self, stop_sequences: Optional[List[str]], **kwargs: Any
- ) -> dict:
- params = self._default_params
- if self.stop_sequences is not None and stop_sequences is not None:
- raise ValueError("`stop` found in both the input and default params.")
- elif self.stop_sequences is not None:
- params["stop_sequences"] = self.stop_sequences
- else:
- params["stop_sequences"] = stop_sequences
- return {**params, **kwargs}
-
- @staticmethod
- def _process_response(response: Any, stop: Optional[List[str]]) -> str:
- text = response["output"]["text"]
- if stop:
- text = enforce_stop_tokens(text, stop)
- return text
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Nebula Service endpoint.
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
- Returns:
- The string generated by the model.
- Example:
- .. code-block:: python
- response = nebula("Tell me a joke.")
- """
- params = self._invocation_params(stop, **kwargs)
- prompt = prompt.strip()
- if "\n" in prompt:
- instruction = prompt.split("\n")[0]
- conversation = "\n".join(prompt.split("\n")[1:])
- else:
- raise ValueError("Prompt must contain instruction and conversation.")
-
- response = completion_with_retry(
- self,
- instruction=instruction,
- conversation=conversation,
- params=params,
- url=f"{self.nebula_service_url}{self.nebula_service_path}",
- )
- _stop = params.get("stop_sequences")
- return self._process_response(response, _stop)
-
-
-def make_request(
- self: Nebula,
- instruction: str,
- conversation: str,
- url: str = f"{DEFAULT_NEBULA_SERVICE_URL}{DEFAULT_NEBULA_SERVICE_PATH}",
- params: Optional[Dict] = None,
-) -> Any:
- """Generate text from the model."""
- params = params or {}
- headers = {
- "Content-Type": "application/json",
- "ApiKey": f"{self.nebula_api_key}",
- }
-
- body = {
- "prompt": {
- "instruction": instruction,
- "conversation": {"text": f"{conversation}"},
- }
- }
-
- # add params to body
- for key, value in params.items():
- body[key] = value
-
- # make request
- response = requests.post(url, headers=headers, json=body)
-
- if response.status_code != 200:
- raise Exception(
- f"Request failed with status code {response.status_code}"
- f" and message {response.text}"
- )
-
- return json.loads(response.text)
-
-
-def _create_retry_decorator(llm: Nebula) -> Callable[[Any], Any]:
- min_seconds = 4
- max_seconds = 10
- # Wait 2^x * 1 second between each retry starting with
- # 4 seconds, then up to 10 seconds, then 10 seconds afterward
- max_retries = llm.max_retries if llm.max_retries is not None else 3
- return retry(
- reraise=True,
- stop=stop_after_attempt(max_retries),
- wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
- retry=(
- retry_if_exception_type((RequestException, ConnectTimeout, ReadTimeout))
- ),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
-
-def completion_with_retry(llm: Nebula, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm)
-
- @retry_decorator
- def _completion_with_retry(**_kwargs: Any) -> Any:
- return make_request(llm, **_kwargs)
-
- return _completion_with_retry(**kwargs)
diff --git a/commune/modules/model/llm/textgen.py b/commune/modules/model/llm/textgen.py
deleted file mode 100644
index 6b409ecb1..000000000
--- a/commune/modules/model/llm/textgen.py
+++ /dev/null
@@ -1,418 +0,0 @@
-import json
-import logging
-from typing import Any, AsyncIterator, Dict, Iterator, List, Optional
-
-import requests
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field
-from langchain.schema.output import GenerationChunk
-
-logger = logging.getLogger(__name__)
-
-
-class TextGen(LLM):
- """text-generation-webui models.
-
- To use, you should have the text-generation-webui installed, a model loaded,
- and --api added as a command-line option.
-
- Suggested installation, use one-click installer for your OS:
- https://github.com/oobabooga/text-generation-webui#one-click-installers
-
- Parameters below taken from text-generation-webui api example:
- https://github.com/oobabooga/text-generation-webui/blob/main/api-examples/api-example.py
-
- Example:
- .. code-block:: python
-
- from langchain.llms import TextGen
- llm = TextGen(model_url="http://localhost:8500")
- """
-
- model_url: str
- """The full URL to the textgen webui including http[s]://host:port """
-
- preset: Optional[str] = None
- """The preset to use in the textgen webui """
-
- max_new_tokens: Optional[int] = 250
- """The maximum number of tokens to generate."""
-
- do_sample: bool = Field(True, alias="do_sample")
- """Do sample"""
-
- temperature: Optional[float] = 1.3
- """Primary factor to control randomness of outputs. 0 = deterministic
- (only the most likely token is used). Higher value = more randomness."""
-
- top_p: Optional[float] = 0.1
- """If not set to 1, select tokens with probabilities adding up to less than this
- number. Higher value = higher range of possible random results."""
-
- typical_p: Optional[float] = 1
- """If not set to 1, select only tokens that are at least this much more likely to
- appear than random tokens, given the prior text."""
-
- epsilon_cutoff: Optional[float] = 0 # In units of 1e-4
- """Epsilon cutoff"""
-
- eta_cutoff: Optional[float] = 0 # In units of 1e-4
- """ETA cutoff"""
-
- repetition_penalty: Optional[float] = 1.18
- """Exponential penalty factor for repeating prior tokens. 1 means no penalty,
- higher value = less repetition, lower value = more repetition."""
-
- top_k: Optional[float] = 40
- """Similar to top_p, but select instead only the top_k most likely tokens.
- Higher value = higher range of possible random results."""
-
- min_length: Optional[int] = 0
- """Minimum generation length in tokens."""
-
- no_repeat_ngram_size: Optional[int] = 0
- """If not set to 0, specifies the length of token sets that are completely blocked
- from repeating at all. Higher values = blocks larger phrases,
- lower values = blocks words or letters from repeating.
- Only 0 or high values are a good idea in most cases."""
-
- num_beams: Optional[int] = 1
- """Number of beams"""
-
- penalty_alpha: Optional[float] = 0
- """Penalty Alpha"""
-
- length_penalty: Optional[float] = 1
- """Length Penalty"""
-
- early_stopping: bool = Field(False, alias="early_stopping")
- """Early stopping"""
-
- seed: int = Field(-1, alias="seed")
- """Seed (-1 for random)"""
-
- add_bos_token: bool = Field(True, alias="add_bos_token")
- """Add the bos_token to the beginning of prompts.
- Disabling this can make the replies more creative."""
-
- truncation_length: Optional[int] = 2048
- """Truncate the prompt up to this length. The leftmost tokens are removed if
- the prompt exceeds this length. Most models require this to be at most 2048."""
-
- ban_eos_token: bool = Field(False, alias="ban_eos_token")
- """Ban the eos_token. Forces the model to never end the generation prematurely."""
-
- skip_special_tokens: bool = Field(True, alias="skip_special_tokens")
- """Skip special tokens. Some specific models need this unset."""
-
- stopping_strings: Optional[List[str]] = []
- """A list of strings to stop generation when encountered."""
-
- streaming: bool = False
- """Whether to stream the results, token by token."""
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling textgen."""
- return {
- "max_new_tokens": self.max_new_tokens,
- "do_sample": self.do_sample,
- "temperature": self.temperature,
- "top_p": self.top_p,
- "typical_p": self.typical_p,
- "epsilon_cutoff": self.epsilon_cutoff,
- "eta_cutoff": self.eta_cutoff,
- "repetition_penalty": self.repetition_penalty,
- "top_k": self.top_k,
- "min_length": self.min_length,
- "no_repeat_ngram_size": self.no_repeat_ngram_size,
- "num_beams": self.num_beams,
- "penalty_alpha": self.penalty_alpha,
- "length_penalty": self.length_penalty,
- "early_stopping": self.early_stopping,
- "seed": self.seed,
- "add_bos_token": self.add_bos_token,
- "truncation_length": self.truncation_length,
- "ban_eos_token": self.ban_eos_token,
- "skip_special_tokens": self.skip_special_tokens,
- "stopping_strings": self.stopping_strings,
- }
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_url": self.model_url}, **self._default_params}
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "textgen"
-
- def _get_parameters(self, stop: Optional[List[str]] = None) -> Dict[str, Any]:
- """
- Performs sanity check, preparing parameters in format needed by textgen.
-
- Args:
- stop (Optional[List[str]]): List of stop sequences for textgen.
-
- Returns:
- Dictionary containing the combined parameters.
- """
-
- # Raise error if stop sequences are in both input and default params
- # if self.stop and stop is not None:
- if self.stopping_strings and stop is not None:
- raise ValueError("`stop` found in both the input and default params.")
-
- if self.preset is None:
- params = self._default_params
- else:
- params = {"preset": self.preset}
-
- # then sets it as configured, or default to an empty list:
- params["stop"] = self.stopping_strings or stop or []
-
- return params
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the textgen web API and return the output.
-
- Args:
- prompt: The prompt to use for generation.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The generated text.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import TextGen
- llm = TextGen(model_url="http://localhost:5000")
- llm("Write a story about llamas.")
- """
- if self.streaming:
- combined_text_output = ""
- for chunk in self._stream(
- prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- combined_text_output += chunk.text
- result = combined_text_output
-
- else:
- url = f"{self.model_url}/api/v1/generate"
- params = self._get_parameters(stop)
- request = params.copy()
- request["prompt"] = prompt
- response = requests.post(url, json=request)
-
- if response.status_code == 200:
- result = response.json()["results"][0]["text"]
- else:
- print(f"ERROR: response: {response}")
- result = ""
-
- return result
-
- async def _acall(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the textgen web API and return the output.
-
- Args:
- prompt: The prompt to use for generation.
- stop: A list of strings to stop generation when encountered.
-
- Returns:
- The generated text.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import TextGen
- llm = TextGen(model_url="http://localhost:5000")
- llm("Write a story about llamas.")
- """
- if self.streaming:
- combined_text_output = ""
- async for chunk in self._astream(
- prompt=prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- combined_text_output += chunk.text
- result = combined_text_output
-
- else:
- url = f"{self.model_url}/api/v1/generate"
- params = self._get_parameters(stop)
- request = params.copy()
- request["prompt"] = prompt
- response = requests.post(url, json=request)
-
- if response.status_code == 200:
- result = response.json()["results"][0]["text"]
- else:
- print(f"ERROR: response: {response}")
- result = ""
-
- return result
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- """Yields results objects as they are generated in real time.
-
- It also calls the callback manager's on_llm_new_token event with
- similar parameters to the OpenAI LLM class method of the same name.
-
- Args:
- prompt: The prompts to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- A generator representing the stream of tokens being generated.
-
- Yields:
- A dictionary like objects containing a string token and metadata.
- See text-generation-webui docs and below for more.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import TextGen
- llm = TextGen(
- model_url = "ws://localhost:5005"
- streaming=True
- )
- for chunk in llm.stream("Ask 'Hi, how are you?' like a pirate:'",
- stop=["'","\n"]):
- print(chunk, end='', flush=True)
-
- """
- try:
- import websocket
- except ImportError:
- raise ImportError(
- "The `websocket-client` package is required for streaming."
- )
-
- params = {**self._get_parameters(stop), **kwargs}
-
- url = f"{self.model_url}/api/v1/stream"
-
- request = params.copy()
- request["prompt"] = prompt
-
- websocket_client = websocket.WebSocket()
-
- websocket_client.connect(url)
-
- websocket_client.send(json.dumps(request))
-
- while True:
- result = websocket_client.recv()
- result = json.loads(result)
-
- if result["event"] == "text_stream":
- chunk = GenerationChunk(
- text=result["text"],
- generation_info=None,
- )
- yield chunk
- elif result["event"] == "stream_end":
- websocket_client.close()
- return
-
- if run_manager:
- run_manager.on_llm_new_token(token=chunk.text)
-
- async def _astream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> AsyncIterator[GenerationChunk]:
- """Yields results objects as they are generated in real time.
-
- It also calls the callback manager's on_llm_new_token event with
- similar parameters to the OpenAI LLM class method of the same name.
-
- Args:
- prompt: The prompts to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- A generator representing the stream of tokens being generated.
-
- Yields:
- A dictionary like objects containing a string token and metadata.
- See text-generation-webui docs and below for more.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import TextGen
- llm = TextGen(
- model_url = "ws://localhost:5005"
- streaming=True
- )
- for chunk in llm.stream("Ask 'Hi, how are you?' like a pirate:'",
- stop=["'","\n"]):
- print(chunk, end='', flush=True)
-
- """
- try:
- import websocket
- except ImportError:
- raise ImportError(
- "The `websocket-client` package is required for streaming."
- )
-
- params = {**self._get_parameters(stop), **kwargs}
-
- url = f"{self.model_url}/api/v1/stream"
-
- request = params.copy()
- request["prompt"] = prompt
-
- websocket_client = websocket.WebSocket()
-
- websocket_client.connect(url)
-
- websocket_client.send(json.dumps(request))
-
- while True:
- result = websocket_client.recv()
- result = json.loads(result)
-
- if result["event"] == "text_stream":
- chunk = GenerationChunk(
- text=result["text"],
- generation_info=None,
- )
- yield chunk
- elif result["event"] == "stream_end":
- websocket_client.close()
- return
-
- if run_manager:
- await run_manager.on_llm_new_token(token=chunk.text)
diff --git a/commune/modules/model/llm/titan_takeoff.py b/commune/modules/model/llm/titan_takeoff.py
deleted file mode 100644
index d87784ace..000000000
--- a/commune/modules/model/llm/titan_takeoff.py
+++ /dev/null
@@ -1,159 +0,0 @@
-from typing import Any, Iterator, List, Mapping, Optional
-
-import requests
-from requests.exceptions import ConnectionError
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.schema.output import GenerationChunk
-
-
-class TitanTakeoff(LLM):
- base_url: str = "http://localhost:8000"
- """Specifies the baseURL to use for the Titan Takeoff API.
- Default = http://localhost:8000.
- """
-
- generate_max_length: int = 128
- """Maximum generation length. Default = 128."""
-
- sampling_topk: int = 1
- """Sample predictions from the top K most probable candidates. Default = 1."""
-
- sampling_topp: float = 1.0
- """Sample from predictions whose cumulative probability exceeds this value.
- Default = 1.0.
- """
-
- sampling_temperature: float = 1.0
- """Sample with randomness. Bigger temperatures are associated with
- more randomness and 'creativity'. Default = 1.0.
- """
-
- repetition_penalty: float = 1.0
- """Penalise the generation of tokens that have been generated before.
- Set to > 1 to penalize. Default = 1 (no penalty).
- """
-
- no_repeat_ngram_size: int = 0
- """Prevent repetitions of ngrams of this size. Default = 0 (turned off)."""
-
- streaming: bool = False
- """Whether to stream the output. Default = False."""
-
- @property
- def _default_params(self) -> Mapping[str, Any]:
- """Get the default parameters for calling Titan Takeoff Server."""
- params = {
- "generate_max_length": self.generate_max_length,
- "sampling_topk": self.sampling_topk,
- "sampling_topp": self.sampling_topp,
- "sampling_temperature": self.sampling_temperature,
- "repetition_penalty": self.repetition_penalty,
- "no_repeat_ngram_size": self.no_repeat_ngram_size,
- }
- return params
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "titan_takeoff"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Titan Takeoff generate endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- prompt = "What is the capital of the United Kingdom?"
- response = model(prompt)
-
- """
- try:
- if self.streaming:
- text_output = ""
- for chunk in self._stream(
- prompt=prompt,
- stop=stop,
- run_manager=run_manager,
- ):
- text_output += chunk.text
- return text_output
-
- url = f"{self.base_url}/generate"
- params = {"text": prompt, **self._default_params}
-
- response = requests.post(url, json=params)
- response.raise_for_status()
- response.encoding = "utf-8"
- text = ""
-
- if "message" in response.json():
- text = response.json()["message"]
- else:
- raise ValueError("Something went wrong.")
- if stop is not None:
- text = enforce_stop_tokens(text, stop)
- return text
- except ConnectionError:
- raise ConnectionError(
- "Could not connect to Titan Takeoff server. \
- Please make sure that the server is running."
- )
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- """Call out to Titan Takeoff stream endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Yields:
- A dictionary like object containing a string token.
-
- Example:
- .. code-block:: python
-
- prompt = "What is the capital of the United Kingdom?"
- response = model(prompt)
-
- """
- url = f"{self.base_url}/generate_stream"
- params = {"text": prompt, **self._default_params}
-
- response = requests.post(url, json=params, stream=True)
- response.encoding = "utf-8"
- for text in response.iter_content(chunk_size=1, decode_unicode=True):
- if text:
- chunk = GenerationChunk(text=text)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(token=chunk.text)
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {"base_url": self.base_url, **{}, **self._default_params}
diff --git a/commune/modules/model/llm/tongyi.py b/commune/modules/model/llm/tongyi.py
deleted file mode 100644
index 80447a619..000000000
--- a/commune/modules/model/llm/tongyi.py
+++ /dev/null
@@ -1,249 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import Any, Callable, Dict, List, Optional
-
-from requests.exceptions import HTTPError
-from tenacity import (
- before_sleep_log,
- retry,
- retry_if_exception_type,
- stop_after_attempt,
- wait_exponential,
-)
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema import Generation, LLMResult
-from langchain.utils import get_from_dict_or_env
-
-logger = logging.getLogger(__name__)
-
-
-def _create_retry_decorator(llm: Tongyi) -> Callable[[Any], Any]:
- min_seconds = 1
- max_seconds = 4
- # Wait 2^x * 1 second between each retry starting with
- # 4 seconds, then up to 10 seconds, then 10 seconds afterwards
- return retry(
- reraise=True,
- stop=stop_after_attempt(llm.max_retries),
- wait=wait_exponential(multiplier=1, min=min_seconds, max=max_seconds),
- retry=(retry_if_exception_type(HTTPError)),
- before_sleep=before_sleep_log(logger, logging.WARNING),
- )
-
-
-def generate_with_retry(llm: Tongyi, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm)
-
- @retry_decorator
- def _generate_with_retry(**_kwargs: Any) -> Any:
- resp = llm.client.call(**_kwargs)
- if resp.status_code == 200:
- return resp
- elif resp.status_code in [400, 401]:
- raise ValueError(
- f"status_code: {resp.status_code} \n "
- f"code: {resp.code} \n message: {resp.message}"
- )
- else:
- raise HTTPError(
- f"HTTP error occurred: status_code: {resp.status_code} \n "
- f"code: {resp.code} \n message: {resp.message}"
- )
-
- return _generate_with_retry(**kwargs)
-
-
-def stream_generate_with_retry(llm: Tongyi, **kwargs: Any) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm)
-
- @retry_decorator
- def _stream_generate_with_retry(**_kwargs: Any) -> Any:
- stream_resps = []
- resps = llm.client.call(**_kwargs)
- for resp in resps:
- if resp.status_code == 200:
- stream_resps.append(resp)
- elif resp.status_code in [400, 401]:
- raise ValueError(
- f"status_code: {resp.status_code} \n "
- f"code: {resp.code} \n message: {resp.message}"
- )
- else:
- raise HTTPError(
- f"HTTP error occurred: status_code: {resp.status_code} \n "
- f"code: {resp.code} \n message: {resp.message}"
- )
- return stream_resps
-
- return _stream_generate_with_retry(**kwargs)
-
-
-class Tongyi(LLM):
- """Tongyi Qwen large language models.
-
- To use, you should have the ``dashscope`` python package installed, and the
- environment variable ``DASHSCOPE_API_KEY`` set with your API key, or pass
- it as a named parameter to the constructor.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Tongyi
- Tongyi = tongyi()
- """
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {"dashscope_api_key": "DASHSCOPE_API_KEY"}
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- client: Any #: :meta private:
- model_name: str = "qwen-plus-v1"
-
- """Model name to use."""
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
-
- top_p: float = 0.8
- """Total probability mass of tokens to consider at each step."""
-
- dashscope_api_key: Optional[str] = None
- """Dashscope api key provide by alicloud."""
-
- n: int = 1
- """How many completions to generate for each prompt."""
-
- streaming: bool = False
- """Whether to stream the results or not."""
-
- max_retries: int = 10
- """Maximum number of retries to make when generating."""
-
- prefix_messages: List = Field(default_factory=list)
- """Series of messages for Chat input."""
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "tongyi"
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and python package exists in environment."""
- get_from_dict_or_env(values, "dashscope_api_key", "DASHSCOPE_API_KEY")
- try:
- import dashscope
- except ImportError:
- raise ImportError(
- "Could not import dashscope python package. "
- "Please install it with `pip install dashscope`."
- )
- try:
- values["client"] = dashscope.Generation
- except AttributeError:
- raise ValueError(
- "`dashscope` has no `Generation` attribute, this is likely "
- "due to an old version of the dashscope package. Try upgrading it "
- "with `pip install --upgrade dashscope`."
- )
-
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling OpenAI API."""
- normal_params = {
- "top_p": self.top_p,
- }
-
- return {**normal_params, **self.model_kwargs}
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Tongyi's generate endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = tongyi("Tell me a joke.")
- """
- params: Dict[str, Any] = {
- **{"model": self.model_name},
- **self._default_params,
- **kwargs,
- }
-
- completion = generate_with_retry(
- self,
- prompt=prompt,
- **params,
- )
- return completion["output"]["text"]
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- generations = []
- params: Dict[str, Any] = {
- **{"model": self.model_name},
- **self._default_params,
- **kwargs,
- }
- if self.streaming:
- if len(prompts) > 1:
- raise ValueError("Cannot stream results with multiple prompts.")
- params["stream"] = True
- for stream_resp in stream_generate_with_retry(
- self, prompt=prompts[0], **params
- ):
- generations.append(
- [
- Generation(
- text=stream_resp["output"]["text"],
- generation_info=dict(
- finish_reason=stream_resp["output"]["finish_reason"],
- ),
- )
- ]
- )
- else:
- for prompt in prompts:
- completion = generate_with_retry(
- self,
- prompt=prompt,
- **params,
- )
- generations.append(
- [
- Generation(
- text=completion["output"]["text"],
- generation_info=dict(
- finish_reason=completion["output"]["finish_reason"],
- ),
- )
- ]
- )
- return LLMResult(generations=generations)
diff --git a/commune/modules/model/llm/utils.py b/commune/modules/model/llm/utils.py
deleted file mode 100644
index 32fdb52eb..000000000
--- a/commune/modules/model/llm/utils.py
+++ /dev/null
@@ -1,8 +0,0 @@
-"""Common utility functions for LLM APIs."""
-import re
-from typing import List
-
-
-def enforce_stop_tokens(text: str, stop: List[str]) -> str:
- """Cut off the text as soon as any stop words occur."""
- return re.split("|".join(stop), text)[0]
diff --git a/commune/modules/model/llm/vertexai.py b/commune/modules/model/llm/vertexai.py
deleted file mode 100644
index b0e6ea2dd..000000000
--- a/commune/modules/model/llm/vertexai.py
+++ /dev/null
@@ -1,452 +0,0 @@
-from __future__ import annotations
-
-from concurrent.futures import Executor, ThreadPoolExecutor
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- ClassVar,
- Dict,
- Iterator,
- List,
- Optional,
- Union,
-)
-
-from langchain.callbacks.manager import (
- AsyncCallbackManagerForLLMRun,
- CallbackManagerForLLMRun,
-)
-from langchain.llms.base import BaseLLM, create_base_retry_decorator
-from langchain.pydantic_v1 import BaseModel, root_validator
-from langchain.schema import (
- Generation,
- LLMResult,
-)
-from langchain.schema.output import GenerationChunk
-from langchain.utilities.vertexai import (
- init_vertexai,
- raise_vertex_import_error,
-)
-
-if TYPE_CHECKING:
- from google.cloud.aiplatform.gapic import (
- PredictionServiceAsyncClient,
- PredictionServiceClient,
- )
- from vertexai.language_models._language_models import (
- TextGenerationResponse,
- _LanguageModel,
- )
-
-
-def _response_to_generation(
- response: TextGenerationResponse,
-) -> GenerationChunk:
- """Convert a stream response to a generation chunk."""
- try:
- generation_info = {
- "is_blocked": response.is_blocked,
- "safety_attributes": response.safety_attributes,
- }
- except Exception:
- generation_info = None
- return GenerationChunk(text=response.text, generation_info=generation_info)
-
-
-def is_codey_model(model_name: str) -> bool:
- """Returns True if the model name is a Codey model.
-
- Args:
- model_name: The model name to check.
-
- Returns: True if the model name is a Codey model.
- """
- return "code" in model_name
-
-
-def _create_retry_decorator(
- llm: VertexAI,
- *,
- run_manager: Optional[
- Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]
- ] = None,
-) -> Callable[[Any], Any]:
- import google.api_core
-
- errors = [
- google.api_core.exceptions.ResourceExhausted,
- google.api_core.exceptions.ServiceUnavailable,
- google.api_core.exceptions.Aborted,
- google.api_core.exceptions.DeadlineExceeded,
- ]
- decorator = create_base_retry_decorator(
- error_types=errors, max_retries=llm.max_retries, run_manager=run_manager
- )
- return decorator
-
-
-def completion_with_retry(
- llm: VertexAI,
- *args: Any,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- def _completion_with_retry(*args: Any, **kwargs: Any) -> Any:
- return llm.client.predict(*args, **kwargs)
-
- return _completion_with_retry(*args, **kwargs)
-
-
-def stream_completion_with_retry(
- llm: VertexAI,
- *args: Any,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- def _completion_with_retry(*args: Any, **kwargs: Any) -> Any:
- return llm.client.predict_streaming(*args, **kwargs)
-
- return _completion_with_retry(*args, **kwargs)
-
-
-async def acompletion_with_retry(
- llm: VertexAI,
- *args: Any,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
-) -> Any:
- """Use tenacity to retry the completion call."""
- retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
-
- @retry_decorator
- async def _acompletion_with_retry(*args: Any, **kwargs: Any) -> Any:
- return await llm.client.predict_async(*args, **kwargs)
-
- return await _acompletion_with_retry(*args, **kwargs)
-
-
-class _VertexAIBase(BaseModel):
- project: Optional[str] = None
- "The default GCP project to use when making Vertex API calls."
- location: str = "us-central1"
- "The default location to use when making API calls."
- request_parallelism: int = 5
- "The amount of parallelism allowed for requests issued to VertexAI models. "
- "Default is 5."
- max_retries: int = 6
- """The maximum number of retries to make when generating."""
- task_executor: ClassVar[Optional[Executor]] = None
- stop: Optional[List[str]] = None
- "Optional list of stop words to use when generating."
- model_name: Optional[str] = None
- "Underlying model name."
-
- @classmethod
- def _get_task_executor(cls, request_parallelism: int = 5) -> Executor:
- if cls.task_executor is None:
- cls.task_executor = ThreadPoolExecutor(max_workers=request_parallelism)
- return cls.task_executor
-
-
-class _VertexAICommon(_VertexAIBase):
- client: "_LanguageModel" = None #: :meta private:
- model_name: str
- "Underlying model name."
- temperature: float = 0.0
- "Sampling temperature, it controls the degree of randomness in token selection."
- max_output_tokens: int = 128
- "Token limit determines the maximum amount of text output from one prompt."
- top_p: float = 0.95
- "Tokens are selected from most probable to least until the sum of their "
- "probabilities equals the top-p value. Top-p is ignored for Codey models."
- top_k: int = 40
- "How the model selects tokens for output, the next token is selected from "
- "among the top-k most probable tokens. Top-k is ignored for Codey models."
- credentials: Any = None
- "The default custom credentials (google.auth.credentials.Credentials) to use "
- "when making API calls. If not provided, credentials will be ascertained from "
- "the environment."
- streaming: bool = False
-
- @property
- def _llm_type(self) -> str:
- return "vertexai"
-
- @property
- def is_codey_model(self) -> bool:
- return is_codey_model(self.model_name)
-
- @property
- def _identifying_params(self) -> Dict[str, Any]:
- """Get the identifying parameters."""
- return {**{"model_name": self.model_name}, **self._default_params}
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- if self.is_codey_model:
- return {
- "temperature": self.temperature,
- "max_output_tokens": self.max_output_tokens,
- }
- else:
- return {
- "temperature": self.temperature,
- "max_output_tokens": self.max_output_tokens,
- "top_k": self.top_k,
- "top_p": self.top_p,
- }
-
- @classmethod
- def _try_init_vertexai(cls, values: Dict) -> None:
- allowed_params = ["project", "location", "credentials"]
- params = {k: v for k, v in values.items() if k in allowed_params}
- init_vertexai(**params)
- return None
-
- def _prepare_params(
- self,
- stop: Optional[List[str]] = None,
- **kwargs: Any,
- ) -> dict:
- stop_sequences = stop or self.stop
- return {**self._default_params, "stop_sequences": stop_sequences, **kwargs}
-
-
-class VertexAI(_VertexAICommon, BaseLLM):
- """Google Vertex AI large language models."""
-
- model_name: str = "text-bison"
- "The name of the Vertex AI large language model."
- tuned_model_name: Optional[str] = None
- "The name of a tuned model. If provided, model_name is ignored."
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that the python package exists in environment."""
- cls._try_init_vertexai(values)
- tuned_model_name = values.get("tuned_model_name")
- model_name = values["model_name"]
- try:
- if not is_codey_model(model_name):
- from vertexai.preview.language_models import TextGenerationModel
-
- if tuned_model_name:
- values["client"] = TextGenerationModel.get_tuned_model(
- tuned_model_name
- )
- else:
- values["client"] = TextGenerationModel.from_pretrained(model_name)
- else:
- from vertexai.preview.language_models import CodeGenerationModel
-
- if tuned_model_name:
- values["client"] = CodeGenerationModel.get_tuned_model(
- tuned_model_name
- )
- else:
- values["client"] = CodeGenerationModel.from_pretrained(model_name)
- except ImportError:
- raise_vertex_import_error()
- return values
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- stream: Optional[bool] = None,
- **kwargs: Any,
- ) -> LLMResult:
- should_stream = stream if stream is not None else self.streaming
- params = self._prepare_params(stop=stop, **kwargs)
- generations = []
- for prompt in prompts:
- if should_stream:
- generation = GenerationChunk(text="")
- for chunk in self._stream(
- prompt, stop=stop, run_manager=run_manager, **kwargs
- ):
- generation += chunk
- generations.append([generation])
- else:
- res = completion_with_retry(
- self, prompt, run_manager=run_manager, **params
- )
- generations.append([_response_to_generation(res)])
- return LLMResult(generations=generations)
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- params = self._prepare_params(stop=stop, **kwargs)
- generations = []
- for prompt in prompts:
- res = await acompletion_with_retry(
- self, prompt, run_manager=run_manager, **params
- )
- generations.append([_response_to_generation(res)])
- return LLMResult(generations=generations)
-
- def _stream(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[GenerationChunk]:
- params = self._prepare_params(stop=stop, **kwargs)
- for stream_resp in stream_completion_with_retry(
- self, prompt, run_manager=run_manager, **params
- ):
- chunk = _response_to_generation(stream_resp)
- yield chunk
- if run_manager:
- run_manager.on_llm_new_token(
- chunk.text,
- chunk=chunk,
- verbose=self.verbose,
- )
-
-
-class VertexAIModelGarden(_VertexAIBase, BaseLLM):
- """Large language models served from Vertex AI Model Garden."""
-
- client: "PredictionServiceClient" = None #: :meta private:
- async_client: "PredictionServiceAsyncClient" = None #: :meta private:
- endpoint_id: str
- "A name of an endpoint where the model has been deployed."
- allowed_model_args: Optional[List[str]] = None
- """Allowed optional args to be passed to the model."""
- prompt_arg: str = "prompt"
- result_arg: str = "generated_text"
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that the python package exists in environment."""
- try:
- from google.api_core.client_options import ClientOptions
- from google.cloud.aiplatform.gapic import (
- PredictionServiceAsyncClient,
- PredictionServiceClient,
- )
- except ImportError:
- raise_vertex_import_error()
-
- if values["project"] is None:
- raise ValueError(
- "A GCP project should be provided to run inference on Model Garden!"
- )
-
- client_options = ClientOptions(
- api_endpoint=f"{values['location']}-aiplatform.googleapis.com"
- )
- values["client"] = PredictionServiceClient(client_options=client_options)
- values["async_client"] = PredictionServiceAsyncClient(
- client_options=client_options
- )
- return values
-
- @property
- def _llm_type(self) -> str:
- return "vertexai_model_garden"
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
- try:
- from google.protobuf import json_format
- from google.protobuf.struct_pb2 import Value
- except ImportError:
- raise ImportError(
- "protobuf package not found, please install it with"
- " `pip install protobuf`"
- )
-
- instances = []
- for prompt in prompts:
- if self.allowed_model_args:
- instance = {
- k: v for k, v in kwargs.items() if k in self.allowed_model_args
- }
- else:
- instance = {}
- instance[self.prompt_arg] = prompt
- instances.append(instance)
-
- predict_instances = [
- json_format.ParseDict(instance_dict, Value()) for instance_dict in instances
- ]
-
- endpoint = self.client.endpoint_path(
- project=self.project, location=self.location, endpoint=self.endpoint_id
- )
- response = self.client.predict(endpoint=endpoint, instances=predict_instances)
- generations: List[List[Generation]] = []
- for result in response.predictions:
- generations.append(
- [Generation(text=prediction[self.result_arg]) for prediction in result]
- )
- return LLMResult(generations=generations)
-
- async def _agenerate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
- try:
- from google.protobuf import json_format
- from google.protobuf.struct_pb2 import Value
- except ImportError:
- raise ImportError(
- "protobuf package not found, please install it with"
- " `pip install protobuf`"
- )
-
- instances = []
- for prompt in prompts:
- if self.allowed_model_args:
- instance = {
- k: v for k, v in kwargs.items() if k in self.allowed_model_args
- }
- else:
- instance = {}
- instance[self.prompt_arg] = prompt
- instances.append(instance)
-
- predict_instances = [
- json_format.ParseDict(instance_dict, Value()) for instance_dict in instances
- ]
-
- endpoint = self.async_client.endpoint_path(
- project=self.project, location=self.location, endpoint=self.endpoint_id
- )
- response = await self.async_client.predict(
- endpoint=endpoint, instances=predict_instances
- )
- generations: List[List[Generation]] = []
- for result in response.predictions:
- generations.append(
- [Generation(text=prediction[self.result_arg]) for prediction in result]
- )
- return LLMResult(generations=generations)
diff --git a/commune/modules/model/llm/vllm.py b/commune/modules/model/llm/vllm.py
deleted file mode 100644
index 537a9bbb6..000000000
--- a/commune/modules/model/llm/vllm.py
+++ /dev/null
@@ -1,166 +0,0 @@
-from typing import Any, Dict, List, Optional
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import BaseLLM
-from langchain.llms.openai import BaseOpenAI
-from langchain.pydantic_v1 import Field, root_validator
-from langchain.schema.output import Generation, LLMResult
-
-
-class VLLM(BaseLLM):
- """VLLM language model."""
-
- model: str = ""
- """The name or path of a HuggingFace Transformers model."""
-
- tensor_parallel_size: Optional[int] = 1
- """The number of GPUs to use for distributed execution with tensor parallelism."""
-
- trust_remote_code: Optional[bool] = False
- """Trust remote code (e.g., from HuggingFace) when downloading the model
- and tokenizer."""
-
- n: int = 1
- """Number of output sequences to return for the given prompt."""
-
- best_of: Optional[int] = None
- """Number of output sequences that are generated from the prompt."""
-
- presence_penalty: float = 0.0
- """Float that penalizes new tokens based on whether they appear in the
- generated text so far"""
-
- frequency_penalty: float = 0.0
- """Float that penalizes new tokens based on their frequency in the
- generated text so far"""
-
- temperature: float = 1.0
- """Float that controls the randomness of the sampling."""
-
- top_p: float = 1.0
- """Float that controls the cumulative probability of the top tokens to consider."""
-
- top_k: int = -1
- """Integer that controls the number of top tokens to consider."""
-
- use_beam_search: bool = False
- """Whether to use beam search instead of sampling."""
-
- stop: Optional[List[str]] = None
- """List of strings that stop the generation when they are generated."""
-
- ignore_eos: bool = False
- """Whether to ignore the EOS token and continue generating tokens after
- the EOS token is generated."""
-
- max_new_tokens: int = 512
- """Maximum number of tokens to generate per output sequence."""
-
- logprobs: Optional[int] = None
- """Number of log probabilities to return per output token."""
-
- dtype: str = "auto"
- """The data type for the model weights and activations."""
-
- download_dir: Optional[str] = None
- """Directory to download and load the weights. (Default to the default
- cache dir of huggingface)"""
-
- vllm_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for `vllm.LLM` call not explicitly specified."""
-
- client: Any #: :meta private:
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that python package exists in environment."""
-
- try:
- from vllm import LLM as VLLModel
- except ImportError:
- raise ImportError(
- "Could not import vllm python package. "
- "Please install it with `pip install vllm`."
- )
-
- values["client"] = VLLModel(
- model=values["model"],
- tensor_parallel_size=values["tensor_parallel_size"],
- trust_remote_code=values["trust_remote_code"],
- dtype=values["dtype"],
- download_dir=values["download_dir"],
- **values["vllm_kwargs"],
- )
-
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling vllm."""
- return {
- "n": self.n,
- "best_of": self.best_of,
- "max_tokens": self.max_new_tokens,
- "top_k": self.top_k,
- "top_p": self.top_p,
- "temperature": self.temperature,
- "presence_penalty": self.presence_penalty,
- "frequency_penalty": self.frequency_penalty,
- "stop": self.stop,
- "ignore_eos": self.ignore_eos,
- "use_beam_search": self.use_beam_search,
- "logprobs": self.logprobs,
- }
-
- def _generate(
- self,
- prompts: List[str],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> LLMResult:
- """Run the LLM on the given prompt and input."""
-
- from vllm import SamplingParams
-
- # build sampling parameters
- params = {**self._default_params, **kwargs, "stop": stop}
- sampling_params = SamplingParams(**params)
- # call the model
- outputs = self.client.generate(prompts, sampling_params)
-
- generations = []
- for output in outputs:
- text = output.outputs[0].text
- generations.append([Generation(text=text)])
-
- return LLMResult(generations=generations)
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "vllm"
-
-
-class VLLMOpenAI(BaseOpenAI):
- """vLLM OpenAI-compatible API client"""
-
- @property
- def _invocation_params(self) -> Dict[str, Any]:
- """Get the parameters used to invoke the model."""
- openai_creds: Dict[str, Any] = {
- "api_key": self.openai_api_key,
- "api_base": self.openai_api_base,
- }
-
- return {
- "model": self.model_name,
- **openai_creds,
- **self._default_params,
- "logit_bias": None,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "vllm-openai"
diff --git a/commune/modules/model/llm/writer.py b/commune/modules/model/llm/writer.py
deleted file mode 100644
index 54a8a5fc2..000000000
--- a/commune/modules/model/llm/writer.py
+++ /dev/null
@@ -1,159 +0,0 @@
-from typing import Any, Dict, List, Mapping, Optional
-
-import requests
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-from langchain.llms.utils import enforce_stop_tokens
-from langchain.pydantic_v1 import Extra, root_validator
-from langchain.utils import get_from_dict_or_env
-
-
-class Writer(LLM):
- """Writer large language models.
-
- To use, you should have the environment variable ``WRITER_API_KEY`` and
- ``WRITER_ORG_ID`` set with your API key and organization ID respectively.
-
- Example:
- .. code-block:: python
-
- from langchain.llms import Writer
- writer = Writer(model_id="palmyra-base")
- """
-
- writer_org_id: Optional[str] = None
- """Writer organization ID."""
-
- model_id: str = "palmyra-instruct"
- """Model name to use."""
-
- min_tokens: Optional[int] = None
- """Minimum number of tokens to generate."""
-
- max_tokens: Optional[int] = None
- """Maximum number of tokens to generate."""
-
- temperature: Optional[float] = None
- """What sampling temperature to use."""
-
- top_p: Optional[float] = None
- """Total probability mass of tokens to consider at each step."""
-
- stop: Optional[List[str]] = None
- """Sequences when completion generation will stop."""
-
- presence_penalty: Optional[float] = None
- """Penalizes repeated tokens regardless of frequency."""
-
- repetition_penalty: Optional[float] = None
- """Penalizes repeated tokens according to frequency."""
-
- best_of: Optional[int] = None
- """Generates this many completions server-side and returns the "best"."""
-
- logprobs: bool = False
- """Whether to return log probabilities."""
-
- n: Optional[int] = None
- """How many completions to generate."""
-
- writer_api_key: Optional[str] = None
- """Writer API key."""
-
- base_url: Optional[str] = None
- """Base url to use, if None decides based on model name."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- extra = Extra.forbid
-
- @root_validator()
- def validate_environment(cls, values: Dict) -> Dict:
- """Validate that api key and organization id exist in environment."""
-
- writer_api_key = get_from_dict_or_env(
- values, "writer_api_key", "WRITER_API_KEY"
- )
- values["writer_api_key"] = writer_api_key
-
- writer_org_id = get_from_dict_or_env(values, "writer_org_id", "WRITER_ORG_ID")
- values["writer_org_id"] = writer_org_id
-
- return values
-
- @property
- def _default_params(self) -> Mapping[str, Any]:
- """Get the default parameters for calling Writer API."""
- return {
- "minTokens": self.min_tokens,
- "maxTokens": self.max_tokens,
- "temperature": self.temperature,
- "topP": self.top_p,
- "stop": self.stop,
- "presencePenalty": self.presence_penalty,
- "repetitionPenalty": self.repetition_penalty,
- "bestOf": self.best_of,
- "logprobs": self.logprobs,
- "n": self.n,
- }
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"model_id": self.model_id, "writer_org_id": self.writer_org_id},
- **self._default_params,
- }
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "writer"
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call out to Writer's completions endpoint.
-
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- .. code-block:: python
-
- response = Writer("Tell me a joke.")
- """
- if self.base_url is not None:
- base_url = self.base_url
- else:
- base_url = (
- "https://enterprise-api.writer.com/llm"
- f"/organization/{self.writer_org_id}"
- f"/model/{self.model_id}/completions"
- )
- params = {**self._default_params, **kwargs}
- response = requests.post(
- url=base_url,
- headers={
- "Authorization": f"{self.writer_api_key}",
- "Content-Type": "application/json",
- "Accept": "application/json",
- },
- json={"prompt": prompt, **params},
- )
- text = response.text
- if stop is not None:
- # I believe this is required since the stop tokens
- # are not enforced by the model parameters
- text = enforce_stop_tokens(text, stop)
- return text
diff --git a/commune/modules/model/llm/xinference.py b/commune/modules/model/llm/xinference.py
deleted file mode 100644
index 3b16838da..000000000
--- a/commune/modules/model/llm/xinference.py
+++ /dev/null
@@ -1,206 +0,0 @@
-from typing import TYPE_CHECKING, Any, Dict, Generator, List, Mapping, Optional, Union
-
-from langchain.callbacks.manager import CallbackManagerForLLMRun
-from langchain.llms.base import LLM
-
-if TYPE_CHECKING:
- from xinference.client import RESTfulChatModelHandle, RESTfulGenerateModelHandle
- from xinference.model.llm.core import LlamaCppGenerateConfig
-
-
-class Xinference(LLM):
- """Wrapper for accessing Xinference's large-scale model inference service.
- To use, you should have the xinference library installed:
-
- .. code-block:: bash
-
- pip install "xinference[all]"
-
- Check out: https://github.com/xorbitsai/inference
- To run, you need to start a Xinference supervisor on one server and Xinference workers on the other servers
-
- Example:
- To start a local instance of Xinference, run
-
- .. code-block:: bash
-
- $ xinference
-
- You can also deploy Xinference in a distributed cluster. Here are the steps:
-
- Starting the supervisor:
-
- .. code-block:: bash
-
- $ xinference-supervisor
-
- Starting the worker:
-
- .. code-block:: bash
-
- $ xinference-worker
-
- Then, launch a model using command line interface (CLI).
-
- Example:
-
- .. code-block:: bash
-
- $ xinference launch -n orca -s 3 -q q4_0
-
- It will return a model UID. Then, you can use Xinference with LangChain.
-
- Example:
-
- .. code-block:: python
-
- from langchain.llms import Xinference
-
- llm = Xinference(
- server_url="http://0.0.0.0:9997",
- model_uid = {model_uid} # replace model_uid with the model UID return from launching the model
- )
-
- llm(
- prompt="Q: where can we visit in the capital of France? A:",
- generate_config={"max_tokens": 1024, "stream": True},
- )
-
- To view all the supported builtin models, run:
-
- .. code-block:: bash
-
- $ xinference list --all
-
- """ # noqa: E501
-
- client: Any
- server_url: Optional[str]
- """URL of the xinference server"""
- model_uid: Optional[str]
- """UID of the launched model"""
- model_kwargs: Dict[str, Any]
- """Key word arguments to be passed to xinference.LLM"""
-
- def __init__(
- self,
- server_url: Optional[str] = None,
- model_uid: Optional[str] = None,
- **model_kwargs: Any,
- ):
- try:
- from xinference.client import RESTfulClient
- except ImportError as e:
- raise ImportError(
- "Could not import RESTfulClient from xinference. Please install it"
- " with `pip install xinference`."
- ) from e
-
- model_kwargs = model_kwargs or {}
-
- super().__init__(
- **{
- "server_url": server_url,
- "model_uid": model_uid,
- "model_kwargs": model_kwargs,
- }
- )
-
- if self.server_url is None:
- raise ValueError("Please provide server URL")
-
- if self.model_uid is None:
- raise ValueError("Please provide the model UID")
-
- self.client = RESTfulClient(server_url)
-
- @property
- def _llm_type(self) -> str:
- """Return type of llm."""
- return "xinference"
-
- @property
- def _identifying_params(self) -> Mapping[str, Any]:
- """Get the identifying parameters."""
- return {
- **{"server_url": self.server_url},
- **{"model_uid": self.model_uid},
- **{"model_kwargs": self.model_kwargs},
- }
-
- def _call(
- self,
- prompt: str,
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> str:
- """Call the xinference model and return the output.
-
- Args:
- prompt: The prompt to use for generation.
- stop: Optional list of stop words to use when generating.
- generate_config: Optional dictionary for the configuration used for
- generation.
-
- Returns:
- The generated string by the model.
- """
- model = self.client.get_model(self.model_uid)
-
- generate_config: "LlamaCppGenerateConfig" = kwargs.get("generate_config", {})
-
- generate_config = {**self.model_kwargs, **generate_config}
-
- if stop:
- generate_config["stop"] = stop
-
- if generate_config and generate_config.get("stream"):
- combined_text_output = ""
- for token in self._stream_generate(
- model=model,
- prompt=prompt,
- run_manager=run_manager,
- generate_config=generate_config,
- ):
- combined_text_output += token
- return combined_text_output
-
- else:
- completion = model.generate(prompt=prompt, generate_config=generate_config)
- return completion["choices"][0]["text"]
-
- def _stream_generate(
- self,
- model: Union["RESTfulGenerateModelHandle", "RESTfulChatModelHandle"],
- prompt: str,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- generate_config: Optional["LlamaCppGenerateConfig"] = None,
- ) -> Generator[str, None, None]:
- """
- Args:
- prompt: The prompt to use for generation.
- model: The model used for generation.
- stop: Optional list of stop words to use when generating.
- generate_config: Optional dictionary for the configuration used for
- generation.
-
- Yields:
- A string token.
- """
- streaming_response = model.generate(
- prompt=prompt, generate_config=generate_config
- )
- for chunk in streaming_response:
- if isinstance(chunk, dict):
- choices = chunk.get("choices", [])
- if choices:
- choice = choices[0]
- if isinstance(choice, dict):
- token = choice.get("text", "")
- log_probs = choice.get("logprobs")
- if run_manager:
- run_manager.on_llm_new_token(
- token=token, verbose=self.verbose, log_probs=log_probs
- )
- yield token
diff --git a/commune/modules/model/model.py b/commune/modules/model/model.py
deleted file mode 100644
index 5b88b2b47..000000000
--- a/commune/modules/model/model.py
+++ /dev/null
@@ -1,524 +0,0 @@
-import os
-from typing import Union, Optional
-from typing import *
-import torch
-import glob
-from torch import nn
-import commune as c
-
-
-"""
-Examples fdef
-
-
-
-"""
-class Model( nn.Module, c.Module):
-
- def __init__(self,
- config = None,
- **kwargs
- ):
-
-
- self.init_model(self)
- # sets to self.config (with kwargs injected)
- config = self.set_config(config, kwargs=kwargs)
-
- @property
- def tag(self):
- if self.config.get('tag', None) == None:
- self.config['tag'] = 'base'
- return self.config['tag']
-
-
- @tag.setter
- def tag(self, tag):
- self.config['tag'] = tag
-
- def init_model(self):
- nn.Module.__init__(self)
- @classmethod
- def train_fleet(cls, *args, **kwargs):
- return cls.module('model.hf').train_fleet(*args, **kwargs)
-
- @classmethod
- def shortcuts(cls, *args, **kwargs):
- return cls.module('model.hf').shortcuts
-
- @property
- def stats(self):
- return self.config.get('stats', {})
-
- @stats.setter
- def stats(self, stats):
- assert isinstance(stats, dict)
- self.config['stats'] = stats
- self.save(keys=['config'])
-
- def reset_stats(self):
- self.stats = {}
-
- def set_stats(self, stats: dict = None,):
- if stats == None:
- stats = {}
- assert isinstance(stats, dict)
- self.stats = stats
-
- @classmethod
- def learn(cls, *args, **kwargs):
- return cls.module('model.hf').learn(*args, **kwargs)
-
- def set_optimizer(self, optimizer:dict=None):
-
- if optimizer == None:
- optimizer = dict(
- module='torch.optim.Adam',
- lr=1e-5
- )
- if isinstance(optimizer, dict):
- module_path = optimizer.pop('module', 'torch.optim.Adam')
- optimizer_kwargs = optimizer.get('params', optimizer.get('kwargs', optimizer))
-
- else:
- raise NotImplementedError(optimizer)
-
- optimizer_class = self.import_object(module_path)
- self.optimizer = optimizer_class(self.parameters(), **optimizer_kwargs)
-
- self.config['optimizer'] = {
- 'module': module_path,
- **optimizer_kwargs,
- }
-
- c.print('OPTIMIZER SET -> ', self.config.optimizer)
-
-
-
-
-
- def set_lr(self, lr:float):
- assert lr > 0, f'lr must be greater than 0, got {lr}'
- for param_group in self.optimizer.param_groups:
- param_group['lr'] = lr
- self.config['optimizer']['lr'] = lr
- set_learning_rate = set_lr
-
- def forward(self, **kwargs) -> Union[Dict, torch.Tensor]:
- # import ipdb; ipdb.set_trace()
- no_grad = kwargs.pop('no_grad', True)
- autocast = kwargs.pop('autocast', True)
- empty_cache = kwargs.pop('empty_cache', True)
- #should the model learn from the input in this forward pass
- train = kwargs['train'] = kwargs.get('train', False)
-
- # set the model to train mode
- if train:
- no_grad = False
- if self.training == False:
- self.train()
- self.training = True
- else:
- if self.training == True:
- self.eval()
- no_grad = True
-
-
- if no_grad:
- with torch.no_grad():
- if autocast:
- with torch.cuda.amp.autocast():
- result = self._forward(**kwargs)
- else:
- result = self._forward(**kwargs)
- else:
- if autocast:
- with torch.cuda.amp.autocast():
- result = self._forward(**kwargs)
- else:
- result = self._forward(**kwargs)
-
-
- if empty_cache:
- torch.cuda.empty_cache()
- return result
-
-
-
- # def process_forward_locals(self, locals):
- # kwargs = self.locals2kwargs(locals)
-
- # # import ipdb; ipdb.set_trace()
- # no_grad = kwargs.pop('no_grad', True)
- # autocast = kwargs.pop('autocast', True)
- # empty_cache = kwargs.pop('empty_cache', True)
- # train = kwargs['train'] = kwargs.get('train', False)
-
- # # set the model to train mode
- # if train:
- # no_grad = False
- # if self.training == False:
- # self.train()
- # self.training = True
- # else:
- # no_grad = True
-
- # if no_grad == True:
- # # need to set no_grad to false to run forward ,or it will recurse forever
- # kwargs['no_grad'] = False
- # with torch.no_grad():
- # return self.forward(**kwargs)
- # if autocast == True:
- # kwargs['autocast'] = False
- # with torch.cuda.amp.autocast():
- # return self.forward(**kwargs)
-
-
-
- def _forward(self, **kwargs):
- raise NotImplementedError
- @property
- def device(self):
- # deepspeed has .module.device to access device
- if 'device' not in self.config:
- self.set_device(device=None)
-
- return self.config['device']
- @device.setter
- def device(self, device):
- # deepspeed has .module.device to access device
- if self.is_number(device):
- device = f'cuda:{device}'
- self.set_device(device)
-
- return self.config['device']
-
- def set_device(self, device:str = None, resolve_device: bool = True):
- '''
- Sets the device for the model and returns the device
- '''
- if device is None:
- device = 'cuda' if torch.cuda.is_available() else 'cpu'
- if resolve_device:
- device = self.resolve_device(device)
- self.to(device)
- self.config['device'] = device
- return device
-
-
-
-
- def resolve_tag(self, tag):
- if tag == None:
- tag = self.tag
- return tag
-
- def save(self,
- tag:str = None,
- trainable_only:bool = True,
- verbose:bool = False,
- keys = None):
- tag = self.resolve_tag(tag)
- path = self.resolve_state_path(tag)
-
- model_state_dict = self.state_dict()
-
- if trainable_only:
- model_state_dict = {k:v for k,v in model_state_dict.items() if v.requires_grad}
-
-
- os.makedirs(path, exist_ok=True)
- state_dict = {
- 'model': model_state_dict,
- 'optimizer': self.optimizer.state_dict(),
- 'config': self.config,
- }
-
- if keys == None:
- keys = list(state_dict.keys())
- else:
- assert isinstance(keys, list), f'keys must be a list, got {keys}'
- assert all([isinstance(k, str) for k in keys]), f'keys must be a list of strings, got {keys}'
- assert all([k in state_dict for k in keys]), f'keys must be a list of strings, got {keys}'
- keys = keys
- state_path_dict = {}
- for k in keys:
- state_path_dict[k] = os.path.join(path, f'{k}.pt')
- self.config['state_path_dict']= {**self.config.get('state_path_dict', {}), **state_path_dict}
-
- for k in keys:
- torch.save(state_dict[k], state_path_dict[k])
-
- return path
-
-
- def check_config(self, config, ensure_keys=[]):
- for k in ensure_keys:
- assert config[k] == self.config[k], f'{k} in config {config[k]} does not match {k} in model {self.config[k]}'
- @classmethod
- def ls_tags(self):
- return self.ls()
-
- @classmethod
- def tags(cls):
- return cls.ls(return_full_path=False)
- def refresh(self, tag = None, verbose:bool = True, keys=['config']) -> Dict[str, Any]:
- tag = tag if tag != None else self.tag
- path = self.resolve_path(tag)
- self.rm_json(path)
- return path
-
- @classmethod
- def get_stats(cls, tag=None):
- if tag == None:
- tag = cls.tags()[0]
- return cls.get_json(cls.resolve_path(tag)+'/config.json').get('stats', {})
-
-
- @classmethod
- def get_stats_table(cls, tag=None):
- stats = cls.get_stats(tag)
- return pd.DataFrame(stats).T
-
-
- def resolve_state_path(self, tag=None):
- tag = tag if tag != None else self.tag
- path = self.resolve_path(tag)
- return path
-
- def reset_params(self):
- self.load_state_dict(self.og_state_dict['model'])
- self.optimizer.load_state_dict(self.og_state_dict['optimizer'])
-
-
- def load(self, tag=None,
- keys:List[str] = None,
- map_location: str = None,
- **kwargs):
- if not hasattr(self, 'load_cnt'):
- self.load_cnt = 0
-
- self.load_cnt += 1
-
- map_location = map_location if map_location else self.device
-
-
- tag = self.resolve_tag(tag)
- path = self.resolve_state_path(tag)
-
-
- if not os.path.exists(path):
- self.print(f'Couldnt find {path}')
- return
-
- path_list = glob.glob(os.path.join(path, '*.pt'))
- loaded_state_dict = {}
-
- # load the keys (model, optimizer, config) into a dict
- for path in path_list:
- key = os.path.basename(path).replace('.pt', '')
- if not os.path.exists(path):
- self.print('No saved model found at {path}')
- return
- loaded_state_dict[key] = torch.load(path)
-
- if 'config' in loaded_state_dict:
- config = loaded_state_dict['config']
- self.check_config(config)
- self.set_config(config)
- # DO WE WANT TO REBUILD THE MODEL WHEN WE LOAD A CONFIG WITH SLIGHTLY DIFFERENT PARAMS
-
- if self.load_cnt == 1:
- # save the original state dict to get the vanilla model
- self.og_state['model'] = {k:states_dict[k] for k,v in loaded_state_dict['model'].keys() if v.requires_grad}
- self.og_state['optimizer'] = self.optimizer.state_dict()
- self.og_state['config'] = self.copy(self.config)
-
- states_dict = self.state_dict()
- if 'model' in loaded_state_dict:
- self.print('Loading model')
- self.update_state_dict(loaded_state_dict['model'])
-
- if 'optimizer' in loaded_state_dict:
- self.print('Loading optimizer')
- self.og_optimizer_state_dict = self.optimizer.state_dict()
- self.optimizer.load_state_dict(loaded_state_dict['optimizer'])
-
- def update_state_dict(self, state_dict:dict):
- assert isinstance(state_dict, dict), f'state_dict must be a dict, got {type(state_dict)}'
- state_dict = self.state_dict()
- state_dict.update(state_dict)
- self.load_state_dict(state_dict)
-
-
-
- def get_state_dict(self, keys=None):
-
- assert isinstance(state_dict, dict), f'state_dict must be a dict, got {type(state_dict)}'
- state_dict = self.state_dict()
- if keys == None:
- keys = state_dict.keys()
- state_dict.update(state_dict)
- self.load_state_dict(state_dict)
-
-
- def set_finetune(self, finetune, set_last_layer_attribute:bool = True) -> Tuple[bool, str]:
- r''' Set to tune only the parameter of the last layer
- Returns:
- reached_last_layer (:type:`bool`):
- If we have set partial of the model to requires grad.
-
- last_layer_name (:type:`string`):
- The name of the last layer that user specified or we found.
- None if the user did not specify and we couldnt find it.
- '''
- self.config['finetune'] = num_layers = finetune
- all = False
- layer_name = None
-
- def find_last_layer(model: torch.nn.Module) -> Optional[str]:
- r''' Recursively find the last layer in a nn.ModuleList
- Args:
- model (:obj:`torch.module`):
- The model (or sub-model) to fine the last layer from.
- Returns:
- name (:type:`str`):
- The name (or sub-name) of the last layer.
- None if not found
- '''
- reverted_child_list = [(name, child) for name, child in model.named_children()]
- reverted_child_list.reverse()
-
- for name, child in reverted_child_list:
- if isinstance(child, nn.ModuleList):
- if num_layers > len(child):
- self.print(f'Number of finetune layers was set higher then the layers avaliable {len(child)}')
- return None
- return (name + '.' +str(len(child) - num_layers))
-
- for name, child in reverted_child_list:
- name_ = find_last_layer(child)
- if name_ != None:
- return (name+'.'+ name_)
-
- return None
-
- if layer_name == None:
- last_layer_name = find_last_layer(self)
- else:
- last_layer_name = layer_name
-
- reached_last_layer = False
-
- # set the non-last layer parameters not to require grads
- if (all) or (last_layer_name == None):
- return False, last_layer_name
-
-
- if set_last_layer_attribute:
- self.last_layer_name = last_layer_name
-
- self.print(f'Set to finetune layer {last_layer_name} and onwards')
-
- for name, param in self.named_parameters():
- if last_layer_name in name or reached_last_layer == True:
- param.requires_grad = True
-
- reached_last_layer = True
- else:
- param.requires_grad = False
-
- if reached_last_layer == False:
- if all:
- self.print('Set to finetune the whole model, this will significantly increase the memory usage.')
- else:
- self.print(f'Cannot identify the last layer of the model with name {last_layer_name}, setting to finetune on all of the parameters.')
-
- self.print(self.num_params(trainable=True), 'trainable parameters')
- self.print(self.num_params(trainable=False), 'untrainable parameters')
- return reached_last_layer, last_layer_name
-
-
- @classmethod
- def resolve_device(cls, device:str = None) -> str:
- return c.resolve_device(device=device)
-
-
-
-
- def num_params(self, trainable:bool = True) -> int:
- total_params = 0
-
- for name, param in self.named_parameters():
- if trainable:
- if param.requires_grad:
- total_params += param.numel()
- else:
- total_params += param.numel()
-
- return total_params
-
- @classmethod
- def serve(cls, *args, **kwargs):
- return cls.base_model().serve(*args, **kwargs)
-
-
- @classmethod
- def serve_fleet(cls, *args, **kwargs):
- return cls.base_model().serve_fleet(*args, **kwargs)
- fleet = serve_fleet
-
- @classmethod
- def base_model(cls):
- return cls.module('model.hf')
-
- @classmethod
- def train_fleet(cls, *args, **kwargs):
- return cls.base_model().train_fleet(*args, **kwargs)
-
- @classmethod
- def test(cls, *args, **kwargs):
- return cls.base_model().test(*args, **kwargs)
- # train = test
-
- @classmethod
- def sandbox(cls, *args,**kwargs):
- self = cls(*args,**kwargs)
- print(self.config)
-
-
- @classmethod
- def quantize(cls,
- model:str,
- dynamic_q_layer : set = {torch.nn.Linear},
- dtype=torch.qint8, **kwargs):
- self = torch.ao.quantization.quantize_dynamic( model, # the original model
- dynamic_q_layer, # a set of layers to dynamically quantize
- dtype=torch.qint8)
- return self
-
- @classmethod
- def resolve_server_name(cls, *args, **kwargs):
- return cls.base_model().resolve_server_name(*args, **kwargs)
-
- @staticmethod
- def get_trainable_params(model: 'nn.Module') -> int:
- """
- Prints the number of trainable parameters in the model.
- """
- trainable_params = 0
- all_param = 0
- for _, param in model.named_parameters():
- all_param += param.numel()
- if param.requires_grad:
- trainable_params += param.numel()
-
- return trainable_params
-
-
-if __name__ == "__main__":
-
- Model.run()
- # TransformerModel.test()
-
-
diff --git a/commune/modules/model/model.yaml b/commune/modules/model/model.yaml
deleted file mode 100644
index 67f96da65..000000000
--- a/commune/modules/model/model.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: Model
\ No newline at end of file
diff --git a/commune/modules/model/openai/experimental/openai_experimental.py b/commune/modules/model/openai/experimental/openai_experimental.py
deleted file mode 100644
index 8f019e969..000000000
--- a/commune/modules/model/openai/experimental/openai_experimental.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import os
-import openai
-import commune as c
-from typing import *
-
-class OpenAI(c.Module):
- def init(self,
- api_key: str = 'OPENAI_API_KEY',
- api_base = None):
- if api_base:
- openai.api_base = api_base
- from dotenv import load_dotenv
- self.set_api_key(api_key)
-
- def set_api_key(self, api_key: str):
- api_key = os.getenv(api_key, api_key)
- self.api_key = api_key
- openai.api_key = api_key
-
- models = [
- 'gpt-3.5-turbo'
- 'gpt-3.5-turbo-0301'
- 'gpt-3.5-turbo-0613'
- 'gpt-3.5-turbo-16k'
- 'gpt-3.5-turbo-16k-0613'
- 'gpt-3.5-turbo-instruct'
- 'gpt-3.5-turbo-instruct-0914'
- ]
-
- def chat(self,
- prompt: str = "Say this is a test",
- model = 'gpt-3.5-turbo-16k-0613',
- max_tokens: int = 1000,
- temperature: float = 0.5) -> str:
- import random
- if not model:
- model = random.choice(self.models)
-
- params = {'max_tokens': max_tokens, 'temperature': temperature}
- try:
- response = openai.ChatCompletion.create(
- model=model, # Optional (user controls the default)
- messages=[{'role': 'user', 'content': prompt}],
- **params
- )
- return response.choices[0].message['content']
- except Exception as e:
- response = openai.Completion.create( model= model, prompt=prompt, **params)
- return response.choices[0].text
-
-
-
- def embed(self, input: Union[List[str],str] = "Say this is a test",
- model = 'text-embedding-ada-002',
- max_tokens: int = 1000,
- temperature: float = 0.5) -> str:
- import random
- if not model:
- model = random.choice(self.models)
-
- params = {'max_tokens': max_tokens, 'temperature': temperature}
- response = openai.Embedding.create(
- model=model, # Optional (user controls the default)
- input=input,
- **params
- )
- response = [r['embedding'] for r in response['data']]
- if isinstance(input, str):
- return response[0]
- return response
-
-
-
- @classmethod
- def test(cls):
- print("Testing OpenAI")
- self = cls()
- print(self.chat('what is 2+2?'))
- input = ['hello', 'world']
- embeddings = self.embed(input)
- assert len(embeddings) == len(input)
- input = 'hello world'
- embeddings = self.embed(input)
- return {'status': 'success'}
-
diff --git a/commune/modules/model/openai/free/openai_free.py b/commune/modules/model/openai/free/openai_free.py
deleted file mode 100644
index 70d3cd87c..000000000
--- a/commune/modules/model/openai/free/openai_free.py
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-import subprocess
-
-import commune as c
-
-class OpenAIFree(c.Module):
- def forward(self, text='hey', **kwargs):
- command = ['bito']
- process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdout, stderr = process.communicate(text.encode())
- output = stdout.decode().strip()
- return output
-
- talk = forward
-
- def ensure_env(self):
- c.cmd('sudo curl https://alpha.bito.ai/downloads/cli/install.sh -fsSL | bash', verbose=True)
- # # Example usage
- # input_prompt = input("InputText: ")
- # output = run_bito(input_prompt)
- # print(output)
\ No newline at end of file
diff --git a/commune/modules/model/openai/model_openai.py b/commune/modules/model/openai/model_openai.py
deleted file mode 100644
index 9de9da115..000000000
--- a/commune/modules/model/openai/model_openai.py
+++ /dev/null
@@ -1,389 +0,0 @@
-import openai
-import os
-import torch
-from typing import Union, List, Any, Dict
-import commune as c
-import json
-# class OpenAILLM(c.Module):
-
-
-class OpenAILLM(c.Module):
-
- prompt = """{x}"""
-
- whitelist = ['generate']
-
- def __init__(self,
- config: Union[str, Dict[str, Any], None] = None,
- **kwargs
- ):
-
- config = self.set_config(config, kwargs=kwargs)
- self.set_api_key(config.api_key)
- self.set_prompt(config.get('prompt', self.prompt))
- self.set_tokenizer(config.tokenizer)
-
-
- def resolve_api_key(self, api_key:str = None) -> str:
- api_key = os.environ.get(api_key, api_key)
- assert isinstance(api_key, str),f"API Key must be a string,{api_key}"
- self.api_key = self.config.api_key = api_key
- return api_key
-
- hour_limit_count = {}
- def ensure_token_limit(self, input:str , output:str ):
- text = input + output
- tokens = self.tokenizer(text)['input_ids']
- hour = c.time() // 3600
- if hour not in self.hour_limit_count:
- self.hour_limit_count[hour] = 0
-
-
- @classmethod
- def random_api_key(cls):
- valid_api_keys = cls.api_keys()
- assert len(valid_api_keys) > 0, "No valid API keys found, please add one via ```c openai add_api_key ```"
- return valid_api_keys[0]
-
- def set_api_key(self, api_key: str = None) -> str:
- api_key = api_key or self.config.api_key
- self.api_key = self.resolve_api_key(api_key)
- openai.api_key = self.api_key
- return {'msg': f"API Key set to {openai.api_key}", 'success': True}
-
- def resolve_prompt(self, *args, prompt = None, **kwargs):
- if prompt == None:
- prompt = self.prompt
- prompt_variables = self.prompt_variables
- else:
- assert isinstance(prompt, str)
- prompt_variables = self.get_prompt_variables(prompt)
-
-
- if len(args) > 0 :
- assert len(args) == len(prompt_variables), f"Number of arguments must match number of prompt variables: {self.prompt_variables}"
- kwargs = dict(zip(prompt_variables, args))
-
- for var in prompt_variables:
- assert var in kwargs
-
- prompt = prompt.format(**kwargs)
- return prompt
-
-
-
- def is_error(self, response):
- return 'error' in response
-
- def is_success(self, response):
- return not self.is_error(response)
-
- def call(self, text):
- return self.forward(text, role='user')
-
-
-
- def forward(self,
- prompt:str = 'sup?',
- model:str = 'gpt-3.5-turbo',
- presence_penalty:float = 0.0,
- frequency_penalty:float = 0.0,
- temperature:float = 0.9,
- max_tokens:int = 100,
- top_p:float = 1,
- choice_idx:int = 0,
- api_key:str = None,
- retry: bool = True,
- role:str = 'user',
- history: list = None,
- **kwargs) -> str:
- t = c.time()
- if not model in self.config.models:
- f"Model must be one of {self.config.models}"
-
-
- openai.api_key = api_key or self.api_key
-
- params = dict(
- model = model,
- presence_penalty = presence_penalty,
- frequency_penalty = frequency_penalty,
- temperature = temperature,
- max_tokens = max_tokens,
- top_p = top_p
- )
-
- messages = [{"role": role, "content": prompt}]
- if history:
- messages = history + messages
-
- try:
-
- response = openai.ChatCompletion.create(messages=messages, **params)
- except Exception as e:
- # if we get an error, try again with a new api key that is in the whitelist
- if retry:
- self.set_api_key(self.random_api_key())
- response = openai.ChatCompletion.create(messages=messages, **params)
-
- else:
- response = c.detailed_error(e)
- return response
-
- output_text = response = response['choices'][choice_idx]['message']['content']
- input_tokens = self.num_tokens(prompt)
- output_tokens = self.num_tokens(output_text)
- latency = c.time() - t
-
- stats = {
- 'prompt': prompt,
- 'response': output_text,
- 'input_tokens': input_tokens,
- 'output_tokens': output_tokens,
- 'latency': latency,
- 'history': history,
- 'timestamp': t,
- }
-
- # self.add_stats(tag=t, stats=stats)
-
- return output_text
-
-
- _stats = None
- _stats_update_time = 0
- @classmethod
- def stats(cls, skip_keys = ['prompt', 'response', 'history'], refresh_interval=5):
- if cls._stats != None or c.time() % refresh_interval > (c.time() - cls._stats_update_time):
- stat_paths = cls.ls('stats')
- cls._stats = [cls.get(path) for path in stat_paths]
- cls._stats_update_time = c.time()
- if cls._stats == None:
- cls._stats = stats
- stats = [{k:v for k,v in cls.get(path).items() if k not in skip_keys} for path in stat_paths]
-
- return stats
-
-
- @classmethod
- def tokens_per_period(cls, timescale='m'):
- stats = cls.stats()
-
- if timescale == 's':
- period = 1
- elif timescale == 'm':
- period = 60
- elif timescale == 'h':
- period = 3600
- else:
- raise NotImplemented(timescale)
-
-
-
- one_hour_ago = c.time() - period
- stats = [s for s in stats if s['timestamp'] > one_hour_ago]
- tokens_per_period = sum([s['input_tokens'] + s['output_tokens'] for s in stats])
- return tokens_per_period
-
- def add_stats(self, tag:str, stats:dict, ):
- self.put(f'stats/{tag}.json', stats)
- saved_stats_paths = self.ls('stats')
- if len(saved_stats_paths) > self.config.max_stats:
- # remove the oldest stat
- sorted(saved_stats_paths, key=lambda x: int(x.split('.')[0]))
- self.rm(saved_stats_paths[0])
-
- return {'msg': f"Saved stats for {tag}", 'success': True}
-
- generate = call = forward
-
- @classmethod
- def chat(cls, *args, **kwargs):
- return cls().forward(*args, **kwargs)
-
- @property
- def history(self):
- return self.config.get('history', [])
- @history.setter
- def history(self, history):
- self.config['history'] = history
-
- def set_prompt(self, prompt: str):
-
- if prompt == None:
- prompt = self.prompt
- self.prompt = prompt
- assert isinstance(self.prompt, str), "Prompt must be a string"
- self.prompt_variables = self.get_prompt_variables(self.prompt)
- @staticmethod
- def get_prompt_variables(prompt):
- variables = []
- tokens = prompt.split('{')
- for token in tokens:
- if '}' in token:
- variables.append(token.split('}')[0])
- return variables
-
-
- api_key_path = 'api_keys'
-
- @classmethod
- def add_api_key(cls, api_key, k=api_key_path):
- api_keys = cls.get(k, [])
- c.print(api_keys)
- if api_key in api_keys:
- return {'error': f'api_key {api_key} already added'}
- verified = cls.verify_api_key(api_key)
- if not verified:
- return {'error': f'api_key {api_key} not verified'}
- api_keys.append(api_key)
- api_keys = list(set(api_keys))
- cls.put(k, api_keys)
- assert api_key in cls.api_keys(), f"API key {api_key} not added"
- return {'msg': f'added api_key {api_key}'}
-
-
- @classmethod
- def add_api_keys(cls, *keys):
- for k in keys:
- cls.add_api_key(k)
-
-
- @classmethod
- def set_api_keys(cls, api_keys: List[str], k: str=api_key_path):
- assert isinstance(api_keys, list)
- cls.put(k, api_keys)
- return {'msg': f'added api_key {api_keys}'}
-
- @classmethod
- def rm_api_key(cls, api_key, k=api_key_path):
-
- api_keys = cls.get('api_keys', [])
- if api_key not in api_keys:
- return {'error': f'api_key {api_key} not found', 'api_keys': api_keys}
-
- api_idx = None
- for i, api_k in enumerate(api_keys):
- if api_key != api_k:
- api_idx = i
- if api_idx == None:
- return {'error': f'api_key {api_key} not found', 'api_keys': api_keys}
-
- del api_keys[api_idx]
- cls.set_api_keys(api_keys)
-
- return {'msg': f'removed api_key {api_key}', 'api_keys': api_keys}
-
- @classmethod
- def update(cls):
- cls.set_api_keys(cls.valid_api_keys())
-
- @classmethod
- def valid_api_key(self):
- return self.valid_api_keys()[0]
-
- @classmethod
- def valid_api_keys(cls, verbose:bool = True):
- api_keys = cls.api_keys()
- valid_api_keys = []
- for api_key in api_keys:
- if verbose:
- c.print(f'Verifying API key: {api_key}', color='blue')
- if cls.verify_api_key(api_key):
- valid_api_keys.append(api_key)
-
- valid_api_keys = c.shuffle(valid_api_keys)
- return valid_api_keys
- valid_keys = verify_api_keys = valid_api_keys
-
- @classmethod
- def api_keys(cls, update:bool = False):
- if update:
- cls.put('api_keys', cls.valid_api_keys())
- return cls.get('api_keys', [])
-
- def num_tokens(self, text:str) -> int:
- num_tokens = 0
- tokens = self.tokenizer.encode(text)
- if isinstance(tokens, list) and isinstance(tokens[0], list):
- for i, token in enumerate(tokens):
- num_tokens += len(token)
- else:
- num_tokens = len(tokens)
- return num_tokens
- @classmethod
- def test(cls, input:str = 'What is the meaning of life?',**kwargs):
- module = cls()
- output = module.generate(input)
- assert isinstance(output, str)
- return {'success': True, 'msg': 'test'}
-
-
- @classmethod
- def verify_api_key(cls, api_key:str, text:str='ping', verbose:bool = True):
- model = cls(api_key=api_key)
- output = model.forward(text, max_tokens=1, api_key=api_key, retry=False)
- if 'error' in output:
- c.print(f'ERROR \u2717 -> {api_key}', output['error'], color='red', verbose=verbose)
- return False
- else:
- # checkmark = u'\u2713'
- c.print(f'Verified \u2713 -> {api_key} ', output, color='green', verbose=verbose)
- return True
-
-
- def set_tokenizer(self, tokenizer: str = 'gpt2'):
- from transformers import AutoTokenizer
-
- try:
- tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast= True)
- except ValueError:
- print('resorting ot use_fast = False')
- tokenizer = AutoTokenizer.from_pretrained(tokenizer, use_fast=False)
-
- tokenizer.pad_token = tokenizer.eos_token
-
- self.tokenizer = tokenizer
-
- return self.tokenizer
-
- def decode_tokens(self,input_ids: Union[torch.Tensor, List[int]], **kwargs) -> Union[str, List[str], torch.Tensor]:
- return self.tokenizer.decode(input_ids, **kwargs)
-
- def encode_tokens(self,
- text: Union[str, List[str], torch.Tensor],
- return_tensors='pt',
- padding=True,
- truncation=True,
- max_length=256,
- **kwargs):
-
- return self.tokenizer(text,
- return_tensors=return_tensors,
- padding=padding,
- truncation=truncation,
- max_length=max_length)
-
- @classmethod
- def validate(cls, text = 'What is the meaning of life?', max_tokens=10):
- prefix = cls.module_path()
- jobs = []
- servers = c.servers(prefix)
- for s in servers:
- job = c.call(module=s,
- fn='forward',
- text=text,
- temperature=0.0,
- max_tokens=max_tokens,
- return_future=True
- )
- jobs.append(job)
- assert len(jobs) > 0, f'No servers found with prefix {prefix}'
- results = c.gather(jobs)
- response = {}
- for s, result in zip(c.servers(prefix), results):
- response[s] = result
-
- return response
-
-
diff --git a/commune/modules/model/openai/model_openai.yaml b/commune/modules/model/openai/model_openai.yaml
deleted file mode 100644
index 273cf3f61..000000000
--- a/commune/modules/model/openai/model_openai.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-api_key : OPENAI_API_KEY
-frequency_penalty: 0.0
-max_tokens: 250
-max_stats: 175
-tokenizer: gpt2
-top_p: 1
-max_tokens_per_hour: 30_000
-models: ['gpt-3.5-turbo-0613', 'gpt-3.5-turbo']
-# tag : base
-
-save : False
diff --git a/commune/modules/namespace.py b/commune/modules/namespace.py
deleted file mode 100644
index 143a4e5b7..000000000
--- a/commune/modules/namespace.py
+++ /dev/null
@@ -1,289 +0,0 @@
-import commune as c
-from typing import *
-
-class Namespace(c.Module):
- network : str = 'local'
-
- @classmethod
- def register_server(cls, name:str, address:str, network=network) -> None:
- namespace = cls.get_namespace(network=network)
- namespace[name] = address
- cls.put_namespace(network, namespace)
- return {'status': 'success', 'msg': f'Block {name} registered to {network}.'}
-
- @classmethod
- def deregister_server(cls, name:str, network=network) -> Dict:
-
- namespace = cls.get_namespace(network=network)
- if name in namespace:
- del namespace[name]
- cls.put_namespace(network, namespace)
- return {'status': 'success', 'msg': f'Block {name} deregistered.'}
- else:
- return {'status': 'failure', 'msg': f'Block {name} not found.'}
-
- @classmethod
- def get_address(cls, name:str, network:str=network, external:bool = True) -> dict:
- namespace = cls.get_namespace(network=network)
- address = namespace.get(name, None)
- if external:
- address = address.replace(c.default_ip, c.ip())
-
- return address
-
- @classmethod
- def get_namespace(cls, search=None, network:str = 'local', update:bool = False) -> dict:
- if network == None:
- network = cls.network
-
- if network == 'subspace':
- namespace = c.module(network)().namespace()
- else:
- if update:
- cls.update_namespace(network=network, full_scan=bool(network=='local'))
- namespace = cls.get(network, {})
- if search != None:
- namespace = {k:v for k,v in namespace.items() if search in k}
- return namespace
-
-
- @classmethod
- def put_namespace(cls, network:str, namespace:dict) -> None:
- assert isinstance(namespace, dict), 'Namespace must be a dict.'
- cls.put(network, namespace)
- return {'status': 'success', 'msg': f'Namespace {network} updated.'}
-
-
-
- @classmethod
- def rm_namespace(cls,network:str) -> None:
- if cls.exists(network):
- cls.rm(network)
- return {'status': 'success', 'msg': f'Namespace {network} removed.'}
- else:
- return {'status': 'failure', 'msg': f'Namespace {network} not found.'}
- @classmethod
- def name2address(cls, name:str, network:str=network ):
- namespace = cls.get_namespace(network=network)
- address = namespace.get(name, None)
- ip = c.ip()
-
- address = address.replace(c.default_ip, ip)
- assert ip in address, f'ip {ip} not in address {address}'
- return address
- @classmethod
- def networks(cls) -> dict:
- return [p.split('/')[-1].split('.')[0] for p in cls.ls()]
-
- @classmethod
- def namespace_exists(cls, network:str) -> bool:
- return cls.exists(network)
-
-
- @classmethod
- def modules(cls, network:List=network) -> List[str]:
- return list(cls.get_namespace(network=network).keys())
-
- @classmethod
- def addresses(cls, network:str=network) -> List[str]:
- return list(cls.get_namespace(network=network).values())
-
- @classmethod
- def module_exists(cls, module:str, network:str=network) -> bool:
- namespace = cls.get_namespace(network=network)
- return bool(module in namespace)
-
- @classmethod
- def update_namespace(cls,
- chunk_size:int=10,
- timeout:int = 10,
- full_scan:bool = True,
- network:str = network,)-> dict:
- '''
- The module port is where modules can connect with each othe.
- When a module is served "module.serve())"
- it will register itself with the namespace_local dictionary.
- '''
-
- namespace = cls.get_namespace(network=network, update=False) # get local namespace from redis
- addresses = c.copy(list(namespace.values()))
-
- if full_scan == True or len(addresses) == 0:
- addresses = [c.default_ip+':'+str(p) for p in c.used_ports()]
-
-
- for i in range(0, len(addresses), chunk_size):
- addresses_chunk = addresses[i:i+chunk_size]
- names_chunk = c.gather([c.async_call(address, fn='server_name', timeout=timeout) for address in addresses_chunk])
- for i in range(len(names_chunk)):
- if isinstance(names_chunk[i], str):
- namespace[names_chunk[i]] = addresses_chunk[i]
-
- cls.put_namespace(network, namespace)
-
- return namespace
-
- @classmethod
- def migrate_namespace(cls, network:str='local'):
- namespace = c.get_json('local_namespace', {})
- c.put_namespace(network, namespace)
-
- @classmethod
- def merge_namespace(cls, from_network:str, to_network:str):
- from_namespace = c.get_namespace(network=from_network)
- to_namespace = c.get_namespace(network=to_network)
- to_namespace.update(from_namespace)
- c.put_namespace(to_network, to_namespace)
- return {'status': 'success', 'msg': f'Namespace {from_network} merged into {to_network}.'}
-
-
- remote_modules_path ='remote_modules'
- @classmethod
- def add_server(cls, address:str, name=None, network:str = 'local', **kwargs):
- module = c.connect(address)
- module_info = module.info()
- name = module_info['name'] if name == None else name
- # check if name exists
- namespace = cls.get_namespace(network=network)
- base_name = c.copy(name)
- cnt = 0
- if address in namespace.values():
- for k, v in c.copy(list(namespace.items())):
- if v == address:
- namespace.pop(k)
-
- while name in namespace:
- name = base_name +address[:3 + cnt].replace('.', '')
- cnt += 1
-
- namespace[name] = address
- cls.put_namespace(network, namespace)
-
- return {'success': True, 'msg': f'Added {address} to {network} modules', 'remote_modules': cls.servers(network=network), 'network': network}
-
-
-
- @classmethod
- def remote_servers(cls, network:str = 'local', **kwargs):
- return c.namespace(network=network)
-
- @classmethod
- def add_servers(cls, *servers, network:str='local', **kwargs):
- responses = []
- for server in servers:
- try:
- response = cls.add_server(server, network=network)
- c.print(response)
- except Exception as e:
- response = {'success': False, 'msg': str(e)}
- c.print(response)
- responses.append(response)
- return responses
-
-
-
- @classmethod
- def servers_info(cls, search=None, network=network) -> List[str]:
- servers = cls.servers(search=search, network=network)
- futures = [c.submit(c.call, kwargs={'module':s, 'fn':'info', 'network': network}, return_future=True) for s in servers]
- return c.wait(futures)
-
- @classmethod
- def rm_server(cls, name, network:str = 'local', **kwargs):
- namespace = cls.namespace(network=network)
- if name in namespace.values():
- for k, v in c.copy(list(namespace.items())):
- if v == name:
- name = k
- break
-
- if name in namespace:
- # reregister
- address = cls.get_address(name, network=network)
- cls.deregister_server(name, network=network)
- remote_modules = c.get(cls.remote_modules_path, {})
- remote_modules.pop(name, None)
- servers = cls.servers(network=network)
- assert cls.server_exists(name, network=network) == False, f'{name} still exists'
- return {'success': True, 'msg': f'removed {address} to remote modules', 'servers': servers, 'network': network}
- else:
- return {'success': False, 'msg': f'{name} does not exist'}
-
-
- @classmethod
- def namespace(cls, search=None, network:str = 'local', **kwargs):
- namespace = cls.get_namespace(network=network, **kwargs)
- if search != None:
- namespace = {k:v for k,v in namespace.items() if search in k}
- return namespace
-
-
-
- @classmethod
- def servers(cls, search=None, network:str = 'local', **kwargs):
- namespace = cls.namespace(search=search, network=network)
- return list(namespace.keys())
-
-
- @classmethod
- def has_server(cls, name:str, network:str = 'local', **kwargs):
- return cls.server_exists(name, network=network)
-
- @classmethod
- def refresh_namespace(cls, network:str):
- return cls.put_namespace(network, {})
- @classmethod
- def network2namespace(self):
- return {network: self.get_namespace(network=network) for network in self.networks()}
- all = network2namespace
- @classmethod
- def server_exists(cls, name:str, network:str = None, prefix_match:bool=False, **kwargs) -> bool:
- servers = cls.servers(network=network, **kwargs)
- if prefix_match:
- server_exists = any([s for s in servers if s.startswith(name)])
-
- else:
- server_exists = bool(name in servers)
-
- return server_exists
-
-
-
- @classmethod
- def test(cls):
- network = 'test'
- network2 = 'test2'
- cls.rm_namespace(network)
- cls.rm_namespace(network2)
-
- assert cls.get_namespace(network=network) == {}, 'Namespace not empty.'
- cls.register_server('test', 'test', network=network)
- assert cls.get_namespace(network=network) == {'test': 'test'}, f'Namespace not updated. {cls.get_namespace(network=network)}'
-
- assert cls.get_namespace(network2) == {}
- cls.register_server('test', 'test', network=network2)
- assert cls.get_namespace(network=network) == {'test': 'test'}, f'Namespace not restored. {cls.get_namespace(network=network)}'
- cls.deregister_server('test', network=network2)
- assert cls.get_namespace(network2) == {}
- cls.rm_namespace(network)
- assert cls.namespace_exists(network) == False
- cls.rm_namespace(network2)
- assert cls.namespace_exists(network2) == False
-
- return {'status': 'success', 'msg': 'Namespace tests passed.'}
-
-
- @classmethod
- def server_exists(cls, name:str, network:str = None, prefix_match:bool=False, **kwargs) -> bool:
- servers = cls.servers(network=network, **kwargs)
- if prefix_match:
- server_exists = any([s for s in servers if s.startswith(name)])
-
- else:
- server_exists = bool(name in servers)
-
- return server_exists
-
-
-
-
diff --git a/commune/modules/network/network.py b/commune/modules/network/network.py
deleted file mode 100644
index 093973961..000000000
--- a/commune/modules/network/network.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# hey/thanks bittensor
-import os
-import urllib
-import commune as c
-import requests
-
-class Network(c.Module):
-
- @staticmethod
- def int_to_ip(int_val: int) -> str:
- r""" Maps an integer to a unique ip-string
- Args:
- int_val (:type:`int128`, `required`):
- The integer representation of an ip. Must be in the range (0, 3.4028237e+38).
-
- Returns:
- str_val (:tyep:`str`, `required):
- The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
-
- Raises:
- netaddr.core.AddrFormatError (Exception):
- Raised when the passed int_vals is not a valid ip int value.
- """
- import netaddr
- return str(netaddr.IPAddress(int_val))
-
- @staticmethod
- def ip_to_int(str_val: str) -> int:
- r""" Maps an ip-string to a unique integer.
- arg:
- str_val (:tyep:`str`, `required):
- The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
-
- Returns:
- int_val (:type:`int128`, `required`):
- The integer representation of an ip. Must be in the range (0, 3.4028237e+38).
-
- Raises:
- netaddr.core.AddrFormatError (Exception):
- Raised when the passed str_val is not a valid ip string value.
- """
- import netaddr
- return int(netaddr.IPAddress(str_val))
-
- @staticmethod
- def ip_version(str_val: str) -> int:
- r""" Returns the ip version (IPV4 or IPV6).
- arg:
- str_val (:tyep:`str`, `required):
- The string representation of an ip. Of form *.*.*.* for ipv4 or *::*:*:*:* for ipv6
-
- Returns:
- int_val (:type:`int128`, `required`):
- The ip version (Either 4 or 6 for IPv4/IPv6)
-
- Raises:
- netaddr.core.AddrFormatError (Exception):
- Raised when the passed str_val is not a valid ip string value.
- """
- import netaddr
- return int(netaddr.IPAddress(str_val).version)
-
- @staticmethod
- def ip__str__(ip_type:int, ip_str:str, port:int):
- """ Return a formatted ip string
- """
- return "/ipv%i/%s:%i" % (ip_type, ip_str, port)
-
-
- @classmethod
- def get_external_ip(cls,verbose: bool = False, default_ip='') -> str:
- r""" Checks CURL/URLLIB/IPIFY/AWS for your external ip.
- Returns:
- external_ip (:obj:`str` `required`):
- Your routers external facing ip as a string.
-
- Raises:
- Exception(Exception):
- Raised if all external ip attempts fail.
- """
- # --- Try curl.
- ip = '0.0.0.0'
- try:
- ip = c.cmd('curl -s ifconfig.me')
- assert isinstance(cls.ip_to_int(ip), int)
- c.print(ip, 'ifconfig.me', verbose=verbose)
- except Exception as e:
- c.print(e, verbose=verbose)
-
- try:
- ip = requests.get('https://api.ipify.org').text
- assert isinstance(cls.ip_to_int(ip), int)
- c.print(ip, 'ipify.org', verbose=verbose)
- except Exception as e:
- c.print(e, verbose=verbose)
-
- # --- Try AWS
- try:
- ip = requests.get('https://checkip.amazonaws.com').text.strip()
- assert isinstance(cls.ip_to_int(ip), int)
- except Exception as e:
- c.print(e, verbose=verbose)
-
- # --- Try myip.dnsomatic
- try:
- process = os.popen('curl -s myip.dnsomatic.com')
- ip = process.readline()
- assert isinstance(cls.ip_to_int(ip), int)
- process.close()
- except Exception as e:
- c.print(e, verbose=verbose)
-
- # --- Try urllib ipv6
- try:
- ip = urllib.request.urlopen('https://ident.me').read().decode('utf8')
- assert isinstance(cls.ip_to_int(ip), int)
- except Exception as e:
- c.print(e, verbose=verbose)
-
- # --- Try Wikipedia
- try:
- ip = requests.get('https://www.wikipedia.org').headers['X-Client-IP']
- assert isinstance(cls.ip_to_int(ip), int)
- except Exception as e:
- c.print(e, verbose=verbose)
-
- if len(ip) == 0:
- ip = default_ip
- return ip
-
- @staticmethod
- def upnpc_create_port_map(port: int):
- r""" Creates a upnpc port map on your router from passed external_port to local port.
-
- Args:
- port (int, `required`):
- The local machine port to map from your external port.
-
- Return:
- external_port (int, `required`):
- The external port mappeclass to the local port on your machine.
-
- Raises:
- Exception (Exception):
- Raised if UPNPC port mapping fails, for instance, if upnpc is not enabled on your router.
- """
-
- try:
- import miniupnpc
- upnp = miniupnpc.UPnP()
- upnp.discoverdelay = 200
- logger.debug('UPNPC: Using UPnP to open a port on your router ...')
- logger.debug('UPNPC: Discovering... delay={}ms', upnp.discoverdelay)
- ndevices = upnp.discover()
- upnp.selectigd()
- logger.debug('UPNPC: ' + str(ndevices) + ' device(s) detected')
-
- ip = upnp.lanaddr
- external_ip = upnp.externalipaddress()
-
- logger.debug('UPNPC: your local ip address: ' + str(ip))
- logger.debug('UPNPC: your external ip address: ' + str(external_ip))
- logger.debug('UPNPC: status = ' + str(upnp.statusinfo()) + " connection type = " + str(upnp.connectiontype()))
-
- # find a free port for the redirection
- external_port = port
- rc = upnp.getspecificportmapping(external_port, 'TCP')
- while rc != None and external_port < 65536:
- external_port += 1
- rc = upnp.getspecificportmapping(external_port, 'TCP')
- if rc != None:
- raise Exception("UPNPC: No available external ports for port mapping.")
-
- logger.info('UPNPC: trying to redirect remote: {}:{} => local: {}:{} over TCP', external_ip, external_port, ip, port)
- upnp.addportmapping(external_port, 'TCP', ip, port, 'Bittensor: %u' % external_port, '')
- logger.info('UPNPC: Create Success')
-
- return external_port
-
- except Exception as e:
- raise Exception(e) from e
diff --git a/commune/modules/process/executor.py b/commune/modules/process/executor.py
deleted file mode 100644
index 529f31a89..000000000
--- a/commune/modules/process/executor.py
+++ /dev/null
@@ -1,202 +0,0 @@
-
-import os
-import sys
-import time
-import queue
-import random
-import weakref
-import itertools
-import multiprocessing as mp
-from loguru import logger
-from typing import Callable
-import concurrent
-from concurrent.futures._base import Future
-import commune as c
-
-
-# Workers are created as daemon processs. This is done to allow the interpreter
-# to exit when there are still idle processs in a ThreadPoolExecutor's process
-# pool (i.e. shutdown() was not called). However, allowing workers to die with
-# the interpreter has two undesirable properties:
-# - The workers would still be running during interpreter shutdown,
-# meaning that they would fail in unpredictable ways.
-# - The workers could be killed while evaluating a work item, which could
-# be bad if the callable being evaluated has external side-effects e.g.
-# writing to a file.
-#
-# To work around this problem, an exit handler is installed which tells the
-# workers to exit when their work queues are empty and then waits until the
-# processs finish.
-
-Task = c.module('executor.task')
-NULL_ENTRY = (sys.maxsize, Task(None, (), {}))
-
-class PoolTaskExecutor(c.Module):
- """Base processpool executor with a priority queue"""
-
- # Used to assign unique process names when process_name_prefix is not supplied.
- _counter = itertools.count().__next__
- # submit.__doc__ = _base.Executor.submit.__doc__
- process_queues = weakref.WeakKeyDictionary()
-
- def __init__(
- self,
- maxsize : int =-1,
- max_workers: int =None,
- process_name_prefix : str ="",
- ):
- """Initializes a new ThreadPoolExecutor instance.
- Args:
- max_workers: The maximum number of processs that can be used to
- execute the given calls.
- process_name_prefix: An optional name prefix to give our processs.
- """
-
- max_workers = (os.cpu_count()) if max_workers is None else max_workers
- if max_workers <= 0:
- raise ValueError("max_workers must be greater than 0")
-
- self.max_workers = max_workers
- self.work_queue = mp.Queue(maxsize=maxsize)
- self.idle_semaphore = mp.Semaphore(0)
- self.processes = []
- self.broken = False
- self.shutdown = False
- self.shutdown_lock = mp.Lock()
- self.process_name_prefix = process_name_prefix or ("ProcessPoolExecutor-%d" % self._counter() )
-
- @property
- def is_empty(self):
- return self.work_queue.empty()
-
-
- def submit(self, fn: Callable, args=None, kwargs=None, timeout=200) -> Future:
- args = args or ()
- kwargs = kwargs or {}
- with self.shutdown_lock:
- if self.broken:
- raise Exception("ThreadPoolExecutor is broken")
-
- if self.shutdown:
- raise RuntimeError("cannot schedule new futures after shutdown")
-
- priority = kwargs.get("priority", 1)
- if "priority" in kwargs:
- del kwargs["priority"]
- task = Task(fn=fn, args=args, kwargs=kwargs, timeout=timeout)
- # add the work item to the queue
- self.work_queue.put((priority, task), block=False)
- # adjust the process count to match the new task
- self.adjust_process_count()
- # return the future (MAYBE WE CAN RETURN THE TASK ITSELF)
- return task.future
-
- def adjust_process_count(self):
- if self.idle_semaphore.acquire(timeout=0):
- return
-
- def weakref_cb(_, q=self.work_queue):
- q.put(NULL_ENTRY)
-
- num_processes = len(self.processes)
- if num_processes < self.max_workers:
- p = mp.Process(target=self.worker, args=(weakref.ref(self, weakref_cb),self.work_queue))
- p.daemon = True
- p.start()
- self.processes.append(p)
- self.process_queues[p] = self.work_queue
-
- def shutdown(self, wait=True):
- with self.shutdown_lock:
- self.shutdown = True
- self.work_queue.put(NULL_ENTRY)
- if wait:
- for t in self.processes:
- try:
- t.join(timeout=2)
- except Exception:
- pass
-
- @staticmethod
- def worker(executor_reference, work_queue):
-
- try:
- while True:
- work_item = work_queue.get(block=True)
- priority = work_item[0]
-
- if priority == sys.maxsize:
- # Wake up queue management process.
- work_queue.put(NULL_ENTRY)
- break
-
- item = work_item[1]
-
- if item is not None:
- item.run()
- # Delete references to object. See issue16284
- del item
- continue
-
- executor = executor_reference()
- # Exit if:
- # - The interpreter is shutting down OR
- # - The executor that owns the worker has been collected OR
- # - The executor that owns the worker has been shutdown.
- if executor is None or executor.shutdown:
- # Flag the executor as shutting down as early as possible if it
- # is not gc-ed yet.
- if executor is not None:
- executor.shutdown = True
- # Notice other workers
- work_queue.put(NULL_ENTRY)
- return
- del executor
- except Exception as e:
- c.print(e, color='red')
- c.print("work_item", work_item, color='red')
- e = c.detailed_error(e)
- c.print("Exception in worker", e, color='red')
-
- @property
- def num_tasks(self):
- return self.work_queue.qsize()
-
- @classmethod
- def as_completed(futures: list):
- assert isinstance(futures, list), "futures must be a list"
- return [f for f in futures if not f.done()]
-
- @staticmethod
- def wait(futures:list) -> list:
- futures = [futures] if not isinstance(futures, list) else futures
- results = []
- for future in c.as_completed(futures):
- results += [future.result()]
- return results
-
-
- @classmethod
- def test(cls):
- def fn(x):
- result = x*2
- return result
-
- self = cls()
- futures = []
- for i in range(100):
- futures += [self.submit(fn=fn, kwargs=dict(x=i))]
- for future in c.tqdm(futures):
- future.result()
- for i in range(100):
- futures += [self.submit(fn=fn, kwargs=dict(x=i))]
-
- results = c.wait(futures)
-
- while self.num_tasks > 0:
- c.print(self.num_tasks, 'tasks remaining', color='red')
-
-
- return {'success': True, 'msg': 'process pool test passed'}
-
-
\ No newline at end of file
diff --git a/commune/modules/process/pool.py b/commune/modules/process/pool.py
deleted file mode 100644
index 1da48d83b..000000000
--- a/commune/modules/process/pool.py
+++ /dev/null
@@ -1,203 +0,0 @@
-
-import os
-import sys
-import time
-import queue
-import random
-import weakref
-import itertools
-import multiprocessing as mp
-from loguru import logger
-from typing import Callable
-import concurrent
-from concurrent.futures._base import Future
-import commune as c
-
-
-# Workers are created as daemon processs. This is done to allow the interpreter
-# to exit when there are still idle processs in a ThreadPoolExecutor's process
-# pool (i.e. shutdown() was not called). However, allowing workers to die with
-# the interpreter has two undesirable properties:
-# - The workers would still be running during interpreter shutdown,
-# meaning that they would fail in unpredictable ways.
-# - The workers could be killed while evaluating a work item, which could
-# be bad if the callable being evaluated has external side-effects e.g.
-# writing to a file.
-#
-# To work around this problem, an exit handler is installed which tells the
-# workers to exit when their work queues are empty and then waits until the
-# processs finish.
-
-Task = c.module('executor.task')
-NULL_ENTRY = (sys.maxsize, Task(None, (), {}))
-
-class PoolTaskExecutor(c.Module):
- """Base processpool executor with a priority queue"""
-
- # Used to assign unique process names when process_name_prefix is not supplied.
- _counter = itertools.count().__next__
- # submit.__doc__ = _base.Executor.submit.__doc__
- process_queues = weakref.WeakKeyDictionary()
-
- def __init__(
- self,
- maxsize : int =-1,
- max_workers: int =None,
- process_name_prefix : str ="",
- ):
- """Initializes a new ThreadPoolExecutor instance.
- Args:
- max_workers: The maximum number of processs that can be used to
- execute the given calls.
- process_name_prefix: An optional name prefix to give our processs.
- """
-
- max_workers = (os.cpu_count()) if max_workers is None else max_workers
- if max_workers <= 0:
- raise ValueError("max_workers must be greater than 0")
-
- self.max_workers = max_workers
- self.work_queue = mp.Queue(maxsize=maxsize)
- self.idle_semaphore = mp.Semaphore(0)
- self.processes = []
- self.broken = False
- self.shutdown = False
- self.shutdown_lock = mp.Lock()
- self.process_name_prefix = process_name_prefix or ("ProcessPoolExecutor-%d" % self._counter() )
-
- @property
- def is_empty(self):
- return self.work_queue.empty()
-
-
- def submit(self, fn: Callable, args=None, kwargs=None, timeout=200) -> Future:
- args = args or ()
- kwargs = kwargs or {}
- with self.shutdown_lock:
- if self.broken:
- raise Exception("ThreadPoolExecutor is broken")
-
- if self.shutdown:
- raise RuntimeError("cannot schedule new futures after shutdown")
-
- priority = kwargs.get("priority", 1)
- if "priority" in kwargs:
- del kwargs["priority"]
- task = Task(fn=fn, args=args, kwargs=kwargs, timeout=timeout)
- # add the work item to the queue
- self.work_queue.put((priority, task), block=False)
- # adjust the process count to match the new task
- self.adjust_process_count()
-
- # return the future (MAYBE WE CAN RETURN THE TASK ITSELF)
- return task.future
-
- def adjust_process_count(self):
- if self.idle_semaphore.acquire(timeout=0):
- return
-
- def weakref_cb(_, q=self.work_queue):
- q.put(NULL_ENTRY)
-
- num_processes = len(self.processes)
- if num_processes < self.max_workers:
- p = mp.Process(target=self.worker, args=(weakref.ref(self, weakref_cb),self.work_queue))
- p.daemon = True
- p.start()
- self.processes.append(p)
- self.process_queues[p] = self.work_queue
-
- def shutdown(self, wait=True):
- with self.shutdown_lock:
- self.shutdown = True
- self.work_queue.put(NULL_ENTRY)
- if wait:
- for t in self.processes:
- try:
- t.join(timeout=2)
- except Exception:
- pass
-
- @staticmethod
- def worker(executor_reference, work_queue):
-
- try:
- while True:
- work_item = work_queue.get(block=True)
- priority = work_item[0]
-
- if priority == sys.maxsize:
- # Wake up queue management process.
- work_queue.put(NULL_ENTRY)
- break
-
- item = work_item[1]
-
- if item is not None:
- item.run()
- # Delete references to object. See issue16284
- del item
- continue
-
- executor = executor_reference()
- # Exit if:
- # - The interpreter is shutting down OR
- # - The executor that owns the worker has been collected OR
- # - The executor that owns the worker has been shutdown.
- if executor is None or executor.shutdown:
- # Flag the executor as shutting down as early as possible if it
- # is not gc-ed yet.
- if executor is not None:
- executor.shutdown = True
- # Notice other workers
- work_queue.put(NULL_ENTRY)
- return
- del executor
- except Exception as e:
- c.print(e, color='red')
- c.print("work_item", work_item, color='red')
- e = c.detailed_error(e)
- c.print("Exception in worker", e, color='red')
-
- @property
- def num_tasks(self):
- return self.work_queue.qsize()
-
- @classmethod
- def as_completed(futures: list):
- assert isinstance(futures, list), "futures must be a list"
- return [f for f in futures if not f.done()]
-
- @staticmethod
- def wait(futures:list) -> list:
- futures = [futures] if not isinstance(futures, list) else futures
- results = []
- for future in c.as_completed(futures):
- results += [future.result()]
- return results
-
-
- @classmethod
- def test(cls):
- def fn(x):
- result = x*2
- return result
-
- self = cls()
- futures = []
- for i in range(100):
- futures += [self.submit(fn=fn, kwargs=dict(x=i))]
- for future in c.tqdm(futures):
- future.result()
- for i in range(100):
- futures += [self.submit(fn=fn, kwargs=dict(x=i))]
-
- results = c.wait(futures)
-
- while self.num_tasks > 0:
- c.print(self.num_tasks, 'tasks remaining', color='red')
-
-
- return {'success': True, 'msg': 'process pool test passed'}
-
-
\ No newline at end of file
diff --git a/commune/modules/process/process.py b/commune/modules/process/process.py
deleted file mode 100644
index b2ed0069d..000000000
--- a/commune/modules/process/process.py
+++ /dev/null
@@ -1,167 +0,0 @@
-import commune as c
-import multiprocessing as mp
-import os
-from typing import *
-class Process(c.Module):
-
- process_map = {}
- @classmethod
- def queue(cls, *args, **kwargs):
- return mp.Queue(*args, **kwargs)
- @classmethod
- def process(cls,fn: Union['callable', str],
- args:list = None,
- kwargs:dict = None,
- daemon:bool = True,
- tag = None,
- name = None,
- start:bool = True,
- tag_seperator:str=':'):
-
- if isinstance(fn, str):
- fn = c.get_fn(fn)
- if args == None:
- args = []
- if kwargs == None:
- kwargs = {}
-
- assert callable(fn), f'target must be callable, got {fn}'
- assert isinstance(args, list), f'args must be a list, got {args}'
- assert isinstance(kwargs, dict), f'kwargs must be a dict, got {kwargs}'
-
- t = mp.Process(target=fn, args=args, kwargs=kwargs)
- t.__dict__['start_time'] = c.time()
- t.daemon = daemon
-
- if start:
- t.start()
- fn_name = fn.__name__
- if tag == None:
- tag = ''
- else:
- tag = str(tag)
-
- if name == None:
- name = fn_name
- name = name + tag_seperator + tag
- cnt = 0
- while name in cls.process_map:
- cnt += 1
- name = fn_name + tag_seperator + tag + str(cnt)
-
- cls.process_map[name] = t
-
- return t
-
- start = process
-
- @classmethod
- def getppid(cls):
- return os.getppid()
-
- @classmethod
- def getpid(cls):
- return os.getpid()
-
- @classmethod
- def get_age(cls, name):
- return c.time() - cls.process_map[name].start_time
-
- @classmethod
- def oldest_process_name(cls):
- oldest_name = None
- oldest_age = 0
- assert len(cls.process_map) > 0, 'no processes to join'
- for name in cls.process_map.keys():
-
- if cls.get_age(name) > oldest_age:
- oldest_age = cls.get_age(name)
- oldest_name = name
-
- return oldest_name
-
- @classmethod
- def oldest_process(cls):
- oldest_name = cls.oldest_process_name()
- oldest_process = cls.process_map[oldest_name]
- return oldest_process
-
- @classmethod
- def oldest_pid(cls):
- return cls.oldest_process().pid
-
- @classmethod
- def n(cls):
- return len(cls.process_map)
-
-
- def join(cls):
- processs = list(cls.process_map.keys())
- for p_name in processs:
- cls.stop(p_name)
- return {'success':True, 'msg':'processes stopped', 'n':cls.n()}
-
- stop_all = join
-
- @classmethod
- def stop(cls, name=None):
- if name == None:
- name = cls.oldest_process_name()
- assert name in cls.process_map, f'process {name} not found'
- p = cls.process_map.pop(name)
- p.join()
- assert p.is_alive() == False, f'process {name} is still alive'
- return {'success':True, 'name':name, 'msg':'process removed', 'n':cls.n()}
-
- @classmethod
- def remove_oldest(cls):
- name = cls.oldest_process_name()
- return cls.remove(name)
-
- @classmethod
- def fleet(cls, fn:str, n=10, tag:str=None, args:list = None, kwargs:dict=None):
- args = args or []
- kwargs = kwargs or {}
- processs = []
- if tag == None:
- tag = ''
- for i in range(n):
- t = cls.process(fn=fn, tag=tag+str(i), *args, **kwargs)
- return cls.process_map
-
-
- @classmethod
- def processes(cls, *args, **kwargs):
- return list(cls.process_map(*args, **kwargs).keys())
-
- @classmethod
- def fn(cls):
- return 1
-
-
- @classmethod
- def test(cls, n=10):
-
-
- for i in range(n):
- cls.start(fn=cls.fn, tag='test', start=True)
- c.print('Started process', i+1, 'of', n, 'processes')
- assert cls.n() == i+1, 'process not added'
-
- for i in range(n):
- cls.stop()
- c.print('Stopped process', i+1, 'of', n, 'processes')
- assert cls.n() == n-i-1, 'process not removed'
- assert cls.n() == 0, 'process not removed'
-
- return {'success':True, 'msg':'processes started and stopped'}
-
- @classmethod
- def semaphore(cls, n:int = 100):
- semaphore = mp.Semaphore(n)
- return semaphore
-
- def __delete__(self):
- self.join()
- return {'success':True, 'msg':'processes stopped'}
-
diff --git a/commune/modules/ray/ray.py b/commune/modules/ray/ray.py
deleted file mode 100644
index 7d7fa0da5..000000000
--- a/commune/modules/ray/ray.py
+++ /dev/null
@@ -1,256 +0,0 @@
-
-import commune as c
-class Ray(c.Module):
- description = 'ray stuff'
- @classmethod
- def ray_context(cls):
- import ray
- import ray
- return ray.runtime_context.get_runtime_context()
-
-
- @classmethod
- def ray_stop(cls):
- return cls.run_command('ray stop')
-
-
- @classmethod
- def ray_put(cls, *items):
- ray = cls.ray_env()
- import ray
- return [ray.put(i) for i in items]
-
-
- @classmethod
- def ray_env(cls):
- import ray
- if not cls.ray_initialized():
- cls.ray_init()
- return ray
-
-
- @classmethod
- def ray_start(cls):
- return cls.run_command('ray start --head')
-
-
- @staticmethod
- def get_ray_context():
- import ray
- return ray.runtime_context.get_runtime_context()
-
-
- @classmethod
- def ensure_ray_context(cls, ray_config:dict = None):
- ray_config = ray_config if ray_config != None else {}
-
- if cls.ray_initialized():
- ray_context = cls.get_ray_context()
- else:
- ray_context = cls.ray_init(init_kwargs=ray_config)
-
- return ray_context
-
-
- @classmethod
- def ray_launch(cls,
- module= None,
- name:Optional[str]=None,
- tag:str=None,
- args:List = None,
- refresh:bool = False,
- kwargs:Dict = None,
- serve: bool = False,
- **actor_kwargs):
-
- launch_kwargs = dict(locals())
- launch_kwargs.update(launch_kwargs.pop('actor_kwargs'))
- launch_kwargs = deepcopy(launch_kwargs)
- ray = cls.ray_env()
- """
- deploys process as an actor or as a class given the config (config)
- """
- args = args if args != None else []
- kwargs = kwargs if kwargs != None else {}
- module_class = None
- if isinstance(module, str):
- module_class = cls.get_module(module)
- elif module == None :
- module_class = cls
-
- else:
- module_class = c.module(module)
-
- name = self.get_server_name(name=name, tag=tag)
- assert isinstance(name, str)
-
- actor_kwargs['name'] = name
- actor_kwargs['refresh'] = refresh
-
- actor = cls.create_actor(module=module_class, args=args, kwargs=kwargs, **actor_kwargs)
- if serve:
- actor = actor.serve(ray_get=False)
-
- return actor
-
-
- @classmethod
- def ray_runtime_context(cls):
- import ray
- return ray.get_runtime_context()
-
-
- @classmethod
- def ray_restart(cls, stop:dict={}, start:dict={}):
- '''
-
- Restart ray cluster
-
- '''
- command_out_dict = {}
- command_out_dict['stop'] = cls.ray_stop(**stop)
- command_out_dict['start'] = cls.ray_start(**start)
- return command_out_dict
-
-
- @classmethod
- def kill_actor(cls, actor, verbose=True):
- import ray
-
- if cls.actor_exists(actor):
- actor = ray.get_actor(actor)
- else:
- if verbose:
- print(f'{actor} does not exist for it to be removed')
- return None
- ray.kill(actor)
-
- return True
-
-
- @staticmethod
- def ray_nodes( *args, **kwargs):
- from ray.experimental.state.api import list_nodes
- return list_nodes(*args, **kwargs)
-
-
- @classmethod
- def ray_import(cls):
- import ray
- return ray
-
-
- @classmethod
- def ray_namespace(cls):
- import ray
- return ray.get_runtime_context().namespace
-
-
- @classmethod
- def ray_wait(cls, *jobs):
- cls.ray_env()
- finished_jobs, running_jobs = ray.wait(jobs)
- return finished_jobs, running_jobs
-
-
- @classmethod
- def ray_actors(cls, state='ALIVE', names_only:bool = True,detail:bool=True, *args, **kwargs):
-
- ray = cls.ray_env()
- from ray.experimental.state.api import list_actors
-
- kwargs['filters'] = kwargs.get('filters', [("state", "=", state)])
- kwargs['detail'] = detail
-
- actor_info_list = list_actors(*args, **kwargs)
- ray_actors = []
- for i, actor_info in enumerate(actor_info_list):
- # resource_map = {'memory': Module.get_memory_info(pid=actor_info['pid'])}
- resource_list = actor_info_list[i].pop('resource_mapping', [])
- resource_map = {}
- for resource in resource_list:
- resource_map[resource['name'].lower()] = resource['resource_ids']
- actor_info_list[i]['resources'] = resource_map
- if names_only:
- ray_actors.append(actor_info_list[i]['name'])
- else:
- ray_actors.append(actor_info_list[i])
-
- return ray_actors
-
-
- @classmethod
- def ray_initialized(cls):
- import ray
- return ray.is_initialized()
-
-
- @classmethod
- def ray_status(cls, *args, **kwargs):
- return cls.run_command('ray status', *args, **kwargs)
-
-
- @classmethod
- def ray_get(cls,*jobs):
- cls.ray_env()
- return ray.get(jobs)
-
-
- @classmethod
- def ray_tasks(cls, running=False, name=None, *args, **kwargs):
- ray = cls.ray_env()
- filters = []
- if running == True:
- filters.append([("scheduling_state", "=", "RUNNING")])
- if isinstance(name, str):
- filters.append([("name", "=", name)])
-
- if len(filters)>0:
- kwargs['filters'] = filters
-
- ray_tasks = ray.experimental.state.api.list_tasks(*args, **kwargs)
- return ray_tasks
-
-
- @classmethod
- def ray_init(cls,init_kwargs={}):
- import ray
- init_kwargs = {**cls.default_ray_env, **init_kwargs}
- ray_context = {}
- if cls.ray_initialized():
- ray_context = cls.ray_runtime_context()
- else:
- ray_context = ray.init(**init_kwargs)
-
- return ray_context
-
-
- @staticmethod
- def ray_objects( *args, **kwargs):
- import ray
- return ray.experimental.state.api.list_objects(*args, **kwargs)
-
-
- @classmethod
- def ray_actor_map(cls, ):
- ray = cls.ray_env()
- actor_list = cls.ray_actors(names_only=False, detail=True)
- actor_map = {}
- for actor in actor_list:
- actor_name = actor.pop('name')
- actor_map[actor_name] = actor
- return actor_map
-
-
- @classmethod
- def ray_actor(cls ,actor_name:str, virtual:bool=True):
- '''
- Gets the ray actor
- '''
- ray = cls.ray_env()
- actor = ray.get_actor(actor_name)
- # actor = Module.add_actor_metadata(actor)
- if virtual:
- actor = cls.virtual_actor(actor=actor)
- return actor
-
diff --git a/commune/modules/remote/remote.py b/commune/modules/remote/remote.py
deleted file mode 100644
index 313e6836f..000000000
--- a/commune/modules/remote/remote.py
+++ /dev/null
@@ -1,288 +0,0 @@
-import commune as c
-
-class Remote(c.Module):
- host_data_path = f'{c.datapath}/hosts.json'
- @classmethod
- def ssh_cmd(cls, *cmd_args, host:str= None, cwd:str=None, verbose=False, **kwargs ):
- """s
- Run a command on a remote server using Remote.
-
- :param host: Hostname or IP address of the remote machine.
- :param port: Remote port (typically 22).
- :param username: Remote username.
- :param password: Remote password.
- :param command: Command to be executed on the remote machine.
- :return: Command output.
- """
- command = ' '.join(cmd_args)
-
- if cwd != None:
- command = f'cd {cwd} ; {command}'
-
-
- import paramiko
- hosts = cls.hosts()
- host_name = host
- if host_name == None:
- host = list(hosts.keys())[0]
- if host_name not in hosts:
- raise Exception(f'Host {host_name} not found')
- host = hosts[host_name]
-
- # Create an Remote client instance.
- client = paramiko.SSHClient()
- # Automatically add the server's host key (this is insecure and used for demonstration;
- # in production, you should have the remote server's public key in known_hosts)
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- # Connect to the remote server
- client.connect(host['host'],
- port=host['port'],
- username=host['user'],
- password=host['pwd'])
-
-
-
- # Execute command
- stdin, stdout, stderr = client.exec_command(command)
- color = c.random_color()
- # Print the output of ls command
- outputs = {'error': '', 'output': ''}
-
- for line in stdout.readlines():
- if verbose:
- c.print(f'[bold]{host_name}[/bold]', line.strip('\n'), color=color)
- outputs['output'] += line
-
- for line in stderr.readlines():
- if verbose:
- c.print(f'[bold]{host_name}[/bold]', line.strip('\n'))
- outputs['error'] += line
-
-
- if len(outputs['error']) == 0:
- outputs = outputs['output']
-
-
- stdin.close()
- stdout.close()
- stderr.close()
- client.close()
-
- return outputs
-
-
- @classmethod
- def add_host(cls,
- host:str = '0.0.0.0',
- port:int = 22,
- user:str = 'root',
- pwd:str = None,
- name : str = None
- ):
-
- hosts = cls.hosts()
- host = {
- 'host': host,
- 'port': port,
- 'user': user,
- 'pwd': pwd
- }
- if name == None:
- cnt = 0
- name = f'{user}{cnt}'
-
- while name in hosts:
- name = f'{user}{cnt}'
- cnt += 1
-
- hosts[name] = host
- cls.save_hosts(hosts)
-
- return {'status': 'success', '': f'Host added', }
-
- @classmethod
- def save_hosts(cls, hosts):
- cls.put_json(cls.host_data_path, hosts)
- @classmethod
- def load_hosts(cls):
- return cls.get_json(cls.host_data_path, {})
-
- @classmethod
- def switch_hosts(cls, path):
- hosts = c.get_json(path)
- cls.save_hosts(hosts)
- return {'status': 'success', 'msg': f'Host data path switched to {path}'}
-
- @classmethod
- def rm_host(cls, name):
- hosts = cls.hosts()
- if name in hosts:
- del hosts[name]
- cls.put_json(cls.host_data_path, hosts)
- return {'status': 'success', 'msg': f'Host {name} removed'}
- else:
- return {'status': 'error', 'msg': f'Host {name} not found'}
-
- @classmethod
- def hosts(cls, search=None):
- hosts = cls.get_json(cls.host_data_path, {})
- if len(hosts) == 0:
- assert False, f'No hosts found, please add your hosts to {cls.host_data_path}'
- if search != None:
- hosts = {k:v for k,v in hosts.items() if search in k}
- return hosts
-
- @classmethod
- def names(cls, search=None):
- return list(cls.hosts(search=search).keys())
-
-
-
- @classmethod
- def n(cls, search=None):
- return len(cls.hosts(search=search))
-
- @classmethod
- def host(self, name):
- hosts = self.hosts()
-
- if name not in hosts:
- raise Exception(f'Host {name} not found')
-
- return hosts[name]
- @classmethod
- def has(cls, name):
- return name in cls.hosts()
-
- @classmethod
- def host_exists(self, name):
- return name in self.hosts()
-
- @classmethod
- def install(self):
- c.cmd('pip3 install paramiko')
-
-
- def test(self):
- # Test Remote
- c.print(self.ssh_cmd('ls'))
-
-
- @classmethod
- def cmd(cls, *commands, search=None, hosts=None, cwd=None, timeout=100, verbose:bool = False, num_trials=5, **kwargs):
-
- output = {}
- host_map = cls.hosts(search=search)
- if hosts != None:
- if isinstance(hosts, str):
- host_map = {k:v for k,v in host_map.items() if hosts in k}
- elif isinstance(hosts, list):
- host_map = {k:v for k,v in host_map.items() if k in hosts}
- else:
- raise Exception(f'hosts must be a list or a string')
- hosts = host_map
- for i in range(num_trials):
- try:
- results = {}
- for host in host_map:
- result_future = c.submit(cls.ssh_cmd, args=commands, kwargs=dict(host=host, cwd=cwd, verbose=verbose,**kwargs), return_future=True)
- results[host] = result_future
- result_values = c.wait(list(results.values()), timeout=timeout)
- results = dict(zip(results.keys(), result_values))
- results = {k:v for k,v in results.items()}
-
- if all([v == None for v in results.values()]):
- raise Exception(f'all results are None')
-
- unfinished_hosts = []
- for k, v in results.items():
- if v == None:
- unfinished_hosts += [k]
- else:
- output[k] = v
-
- host_map = {k:v for k,v in host_map.items() if k in unfinished_hosts}
-
- if len(host_map) == 0:
- break
-
- except Exception as e:
- c.print('Retrying')
- c.print(c.detailed_error(e))
- continue
-
-
-
-
- return output
-
-
- @classmethod
- def add_admin(cls):
- root_key_address = c.root_key().ss58_address
- return cls.cmd(f'c add_admin {root_key_address}')
-
- @classmethod
- def is_admin(cls):
- root_key_address = c.root_key().ss58_address
- results = cls.cmd(f'c is_admin {root_key_address}')
- for host, r in results.items():
- results[host] = bool(r)
- return results
-
- @classmethod
- def add_servers(cls, *args, add_admins:bool=False, network='remote'):
-
-
- if add_admins:
- c.print('Adding admin')
- cls.add_admin()
- servers = list(cls.cmd('c addy', verbose=True).values())
- for i, server in enumerate(servers):
- if server.endswith('\n'):
- servers[i] = server[:-1]
- c.add_servers(*servers, network=network)
- cls.check_servers()
- servers = c.servers(network=network)
- return {'status': 'success', 'msg': f'Servers added', 'servers': servers}
-
- @classmethod
- def servers(self, network='remote'):
- return c.servers(network=network)
-
- @classmethod
- def namespace(self, network='remote'):
- return c.namespace(network=network)
-
- @classmethod
- def get_address(self, name):
- return c.get_address(name)
-
-
- @classmethod
- def addresses(self, network='remote'):
- return c.addresses(network=network)
-
- @classmethod
- def servers_info(self, network='remote'):
- return c.servers_info(network=network)
- @classmethod
- def push(cls,**kwargs):
- return [c.push(), cls.pull()]
-
- @classmethod
- def pull(cls):
- return c.rcmd('c pull')
- @classmethod
- def check_servers(cls):
- for m,a in c.namespace(network='remote').items():
- try:
- result = c.call(a)
- c.print(f'{c.emoji("checkmaark")} [bold green]{m} --> {a}[/bold green] {c.emoji("checkmark")}')
- except Exception as e:
- c.rm_server(a, network='remote')
- c.print('failed')
-
-
-
diff --git a/commune/modules/router/router.py b/commune/modules/router/router.py
deleted file mode 100644
index b015da0af..000000000
--- a/commune/modules/router/router.py
+++ /dev/null
@@ -1,160 +0,0 @@
-import commune as c
-Thread = c.module('thread')
-import asyncio
-import gc
-class Router(Thread):
- def __init__(self,
- fn = None,
- num_workers:int = 4,
- max_queue_size:int = 100,
- verbose: bool = False,
- save_outputs : bool= False,
- path = None):
-
-
- self.path = path if path != None else self.resolve_path('store')
-
- self.verbose = verbose
-
- self.input_queue = self.queue(maxsize=max_queue_size)
- self.output_queue = self.queue(maxsize=max_queue_size)
- self.save_outputs = save_outputs
-
-
- for i in range(num_workers):
- self.thread(fn=self.run, kwargs=dict(fn=fn, queue = self.input_queue, semaphore=self.semaphore(num_workers), output_queue=self.output_queue), tag=f'worker_{i}')
-
- self.fn = fn
-
- # run output collector as a thread to collect the output from the output_queue
- c.thread(self.output_collector, kwargs=dict(output_queue=self.output_queue))
-
-
-
-
- def submit(self,
- fn = None,
- kwargs= None,
- wait_until_response:bool = False,
- timeout = 10,
- sleep_inteval = 0.01):
- start_time = c.time()
- if kwargs == None:
- kwargs = {}
- assert 'kwargs_key' not in kwargs, 'kwargs_key is a reserved key'
-
- kwargs_key = c.hash(kwargs) +'_T'+str(c.time())
- input = {'kwargs_key': kwargs_key, 'kwargs': kwargs, 'fn': fn}
- kwargs['kwargs_key'] = kwargs_key
- self.input_queue.put(kwargs)
-
- if wait_until_response:
- c.print('Waiting for response')
- start_time = c.time()
- while kwargs_key not in self.outputs:
- asyncio.sleep(sleep_inteval)
- if c.time() - start_time > timeout:
- raise TimeoutError(f'Timeout after {timeout} seconds')
- return self.outputs.pop(kwargs_key)
-
- return {'status': 'success', 'key': kwargs_key}
-
- def output_collector(self, output_queue:'mp.Queue', sleep_time:float=0.0):
- '''
- Collects output from the output_queue and stores it in self.outputs
- '''
- while True:
- c.sleep(sleep_time)
- output = output_queue.get()
- if self.save_outputs:
- self.save_output(output)
-
- def save_output(self, output):
- kwargs_key = output.pop('key')
- output_path = self.resolve_output_path(kwargs_key)
- self.put(output_path, output)
-
- def get_output(self, kwargs_key):
- output_path = self.resolve_output_path(kwargs_key)
- return self.get(output_path)
-
- def resolve_output_path(self, kwargs_key):
- return f'{self.tag}/'+kwargs_key
-
- def ls_outputs(self):
- return self.ls(f'{self.tag}')
- def output_exists(self, kwargs_key):
- return self.exists(self.resolve_output_path(kwargs_key))
-
- def time2output(self):
- outputs = self.ls_outputs()
- timestamp2output = {int(output.split('_T')[-1].split('.')[0]): output for output in outputs}
- return timestamp2output
-
- def oldest_output(self):
- timestamp2output = self.time2output()
- oldest_timestamp = min(timestamp2output.keys())
- return timestamp2output[oldest_timestamp]
-
- def run(self, fn:'callable', queue:'mp.Queue', output_queue:'mp.Queue', semaphore:'mp.Semaphore'):
- c.new_event_loop()
- while True:
-
- try:
- kwargs = queue.get()
- kwargs_key = kwargs.pop('kwargs_key')
- if 'fn' in kwargs:
- tmp_fn = kwargs.pop('fn')
- assert callable(tmp_fn), f'fn must be callable, got {tmp_fn}'
- tmp_fn(**kwargs)
- result = fn(**kwargs)
- output_queue.put({'key': kwargs_key, 'result': result, 'kwargs': kwargs, 'time': c.time()})
- ## remove memory
- del kwargs
- del result
- del kwargs_key
- # garbage collect
- gc.collect()
- except Exception as e:
- c.print({'status': 'error', 'error': e})
-
-
-
- def is_full(self):
- return self.input_queue.full()
-
-
- @property
- def num_tasks(self):
- return self.input_queue.qsize()
-
-
-
- def __del__(self):
- self.close()
-
-
-
-
- @classmethod
- def test(cls):
- def fn(x):
- result = x*2
- return result
-
- self = cls(fn=fn)
- for i in range(100):
- self.submit(kwargs=dict(x=i))
-
- while self.num_tasks > 0:
- c.print(self.num_tasks)
-
-
-
-
-
-
-
-
-
-
diff --git a/commune/modules/serializer/serializer.py b/commune/modules/serializer/serializer.py
deleted file mode 100644
index 7bdb0d83d..000000000
--- a/commune/modules/serializer/serializer.py
+++ /dev/null
@@ -1,358 +0,0 @@
-""" An interface for serializing and deserializing bittensor tensors"""
-
-# I DONT GIVE A FUCK LICENSE (IDGAF)
-# Do whatever you want with this code
-# Dont pull up with your homies if it dont work.
-import numpy as np
-import torch
-import msgpack
-import msgpack_numpy
-from typing import Tuple, List, Union, Optional
-import sys
-import os
-import asyncio
-from copy import deepcopy
-from munch import Munch
-
-import commune as c
-import json
-
-
-class Serializer(c.Module):
- r""" Bittensor base serialization object for converting between DataBlock and their
- various python tensor equivalents. i.e. torch.Tensor or tensorflow.Tensor
- """
- @staticmethod
- def resolve_key_list(x):
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
- elif type(x) in [tuple, set]:
- # convert to list, to format as json
- x = list(x)
- k_list = list(range(len(x)))
- else:
- raise Exception(f'{type(x)} not supported to get the keylist fam')
-
- python_types = [int, bool, float, tuple, dict, list, str, type(None)]
- def serialize(self,x:dict, mode = 'str'):
- x = c.copy(x)
- x_type = type(x)
- if x_type in [dict, list, tuple, set]:
- k_list = []
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
- elif type(x) in [tuple, set]:
- # convert to list, to format as json
- x = list(x)
- k_list = list(range(len(x)))
-
- for k in k_list:
- x[k] = self.resolve_value(v=x[k])
- else:
- x = self.resolve_value(v=x)
-
-
- if mode == 'str':
- if isinstance(x, dict):
- x = self.dict2str(x)
- elif mode == 'bytes':
- if isinstance(x, dict):
- x = self.dict2bytes(x)
- elif isinstance(x, str):
- x = self.str2bytes(x)
- elif mode == 'dict' or mode == None:
- x = x
- else:
- raise Exception(f'{mode} not supported')
-
- return x
-
-
- def resolve_value(self, v):
- new_value = None
- v_type = type(v)
- if v_type in [dict, list, tuple, set]:
- new_value = self.serialize(x=v, mode=None)
- else:
- # GET THE TYPE OF THE VALUE
- str_v_type = self.get_type_str(data=v)
- if hasattr(self, f'serialize_{str_v_type}'):
- # SERIALIZE MODE ON
- v = getattr(self, f'serialize_{str_v_type}')(data=v)
- new_value = {'data': v, 'data_type': str_v_type, 'serialized': True}
- else:
- # SERIALIZE MODE OFF
- new_value = v
-
- return new_value
-
-
- def is_serialized(self, data):
- if isinstance(data, dict) and \
- data.get('serialized', False) == True and \
- 'data' in data and 'data_type' in data:
- return True
- else:
- return False
-
- def deserialize(self, x) -> object:
- """Serializes a torch object to DataBlock wire format.
- """
- if isinstance(x, str):
- x = self.str2dict(x)
-
-
- is_single = isinstance(x,dict) and all([k in x for k in ['data', 'data_type', 'serialized']])
- if is_single:
- x = [x]
- k_list = []
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
- elif type(x) in [tuple, set]:
- # convert to list, to format as json
- x = list(x)
- k_list = list(range(len(x)))
-
- for k in k_list:
- v = x[k]
- if self.is_serialized(v):
- data_type = v['data_type']
- data = v['data']
- if hasattr(self, f'deserialize_{data_type}'):
- x[k] = getattr(self, f'deserialize_{data_type}')(data=data)
- elif type(v) in [dict, list, tuple, set]:
- x[k] = self.deserialize(x=v)
- if is_single:
- x = x[0]
- return x
-
- """
- ################ BIG DICT LAND ############################
- """
-
- def serialize_pandas(self, data: 'pd.DataFrame') -> 'DataBlock':
- data = data.to_dict()
- data = self.dict2bytes(data=data)
- return data
-
- def deserialize_pandas(self, data: bytes) -> 'pd.DataFrame':
- data = self.bytes2dict(data=data)
- data = pd.DataFrame.from_dict(data)
- return data
-
- def serialize_dict(self, data: dict) -> str :
- data = self.dict2bytes(data=data)
- return data
-
- def deserialize_dict(self, data: bytes) -> dict:
- data = self.bytes2dict(data=data)
- return data
-
- def serialize_bytes(self, data: dict) -> bytes:
- data = data
-
- def deserialize_bytes(self, data: bytes) -> 'DataBlock':
- if isinstance(data, str):
- data = self.str2bytes(data)
- return data
-
- def serialize_munch(self, data: dict) -> str:
- data=self.munch2dict(data)
- data = self.dict2str(data=data)
- return data
-
- def deserialize_munch(self, data: bytes) -> 'Munch':
- data = self.str2dict(data=data)
- data = self.dict2munch(data)
- return data
-
- def dict2bytes(self, data:dict) -> bytes:
- data_json_str = json.dumps(data)
- data_json_bytes = msgpack.packb(data_json_str)
- return data_json_bytes
- def dict2str(self, data:dict) -> bytes:
- data_json_str = json.dumps(data)
- return data_json_str
- def str2dict(self, data:str) -> bytes:
- data_json_str = json.loads(data)
- return data_json_str
-
- @classmethod
- def hex2str(cls, x, **kwargs):
- return x.hex()
-
- bytes2str = hex2str
-
- @classmethod
- def str2hex(cls, x, **kwargs):
- return bytes.fromhex(x)
-
- str2bytes = str2hex
-
-
-
- def bytes2dict(self, data:bytes) -> dict:
- json_object_bytes = msgpack.unpackb(data)
- return json.loads(json_object_bytes)
-
- """
- ################ BIG TORCH LAND ############################
- """
- def torch2bytes(self, data:'torch.Tensor')-> bytes:
- return self.numpy2bytes(self.torch2numpy(data))
-
- def torch2numpy(self, data:'torch.Tensor')-> np.ndarray:
- if data.requires_grad:
- data = data.detach()
- data = data.cpu().numpy()
- return data
-
-
- def numpy2bytes(self, data:np.ndarray)-> bytes:
- output = msgpack.packb(data, default=msgpack_numpy.encode)
- return output
-
- def bytes2torch(self, data:bytes, ) -> 'torch.Tensor':
- numpy_object = self.bytes2numpy(data)
-
- int64_workaround = bool(numpy_object.dtype == np.int64)
- if int64_workaround:
- numpy_object = numpy_object.astype(np.float64)
- torch_object = torch.tensor(numpy_object)
- if int64_workaround:
- dtype = torch.int64
- return torch_object
-
- def bytes2numpy(self, data:bytes) -> np.ndarray:
- output = msgpack.unpackb(data, object_hook=msgpack_numpy.decode)
- return output
-
-
- def deserialize_torch(self, data: dict) -> torch.Tensor:
- from safetensors.torch import load
- if isinstance(data, str):
- data = self.str2bytes(data)
- data = load(data)
- return data['data']
-
-
-
- def serialize_torch(self, data: torch.Tensor) -> 'DataBlock':
- from safetensors.torch import save
- output = save({'data':data})
- return self.bytes2str(output)
-
-
- def serialize_numpy(self, data: 'np.ndarray') -> 'np.ndarray':
- data = self.numpy2bytes(data)
- return self.bytes2str(data)
-
- def deserialize_numpy(self, data: bytes) -> 'np.ndarray':
- if isinstance(data, str):
- data = self.str2bytes(data)
- return self.bytes2numpy(data)
-
-
-
- def get_type_str(self, data):
- data_type = str(type(data)).split("'")[1]
- if 'Munch' in data_type:
- data_type = 'munch'
- if 'Tensor' in data_type or 'torch' in data_type:
- data_type = 'torch'
- if 'ndarray' in data_type:
- data_type = 'numpy'
- if 'DataFrame' in data_type:
- data_type = 'pandas'
- return data_type
-
- @classmethod
- def test_serialize(cls):
- module = Serializer()
- data = {'bro': {'fam': torch.ones(2,2), 'bro': [torch.ones(1,1)]}}
- proto = module.serialize(data)
- module.deserialize(proto)
-
- @classmethod
- def test_deserialize(cls):
- module = Serializer()
-
- t = c.time()
- data = {'bro': {'fam':[[torch.randn(100,1000), torch.randn(100,1000)]], 'bro': [torch.ones(1,1)]}}
- proto = module.serialize(data)
- data = module.deserialize(proto)
- c.print(t - c.time())
-
- # return True
-
- @classmethod
- def test(cls, size=1):
- self = cls()
- stats = {}
- data = {'bro': {'fam': torch.randn(size,size), 'bro': [torch.ones(1000,500)] , 'bro2': [np.ones((100,1000))]}}
-
- t = c.time()
- serialized_data = self.serialize(data)
- assert isinstance(serialized_data, str), f"serialized_data must be a str, not {type(serialized_data)}"
- deserialized_data = self.deserialize(serialized_data)
-
- assert deserialized_data['bro']['fam'].shape == data['bro']['fam'].shape
- assert deserialized_data['bro']['bro'][0].shape == data['bro']['bro'][0].shape
-
- stats['elapsed_time'] = c.time() - t
- stats['size_bytes'] = c.sizeof(data)
- stats['size_bytes_compressed'] = c.sizeof(serialized_data)
- stats['size_deserialized_data'] = c.sizeof(deserialized_data)
- stats['compression_ratio'] = stats['size_bytes'] / stats['size_bytes_compressed']
- stats['mb_per_second'] = c.round((stats['size_bytes'] / stats['elapsed_time']) / 1e6, 3)
- c.print(stats)
-
-
-
- data = torch.randn(size,size)
- t = c.time()
- serialized_data = self.serialize(data)
- assert isinstance(serialized_data, str), f"serialized_data must be a str, not {type(serialized_data)}"
- deserialized_data = self.deserialize(serialized_data)
- c.print(deserialized_data, data)
- assert deserialized_data.shape == data.shape
-
- stats['elapsed_time'] = c.time() - t
- stats['size_bytes'] = c.sizeof(data)
- stats['size_bytes_compressed'] = c.sizeof(serialized_data)
- stats['size_deserialized_data'] = c.sizeof(deserialized_data)
- stats['compression_ratio'] = stats['size_bytes'] / stats['size_bytes_compressed']
- stats['mb_per_second'] = c.round((stats['size_bytes'] / stats['elapsed_time']) / 1e6, 3)
- c.print(stats)
- c.print(serialized_data)
-
-
- data = np.random.randn(size,size)
- t = c.time()
- serialized_data = self.serialize(data, mode='str')
- assert isinstance(serialized_data, str), f"serialized_data must be a str, not {type(serialized_data)}"
- deserialized_data = self.deserialize(serialized_data)
- c.print(deserialized_data, data)
- assert deserialized_data.shape == data.shape
-
- stats['elapsed_time'] = c.time() - t
- stats['size_bytes'] = c.sizeof(data)
- stats['size_bytes_compressed'] = c.sizeof(serialized_data)
- stats['size_deserialized_data'] = c.sizeof(deserialized_data)
- stats['compression_ratio'] = stats['size_bytes'] / stats['size_bytes_compressed']
- stats['mb_per_second'] = c.round((stats['size_bytes'] / stats['elapsed_time']) / 1e6, 3)
- c.print(stats)
- c.print(serialized_data)
-
- # for data in [100, 'broooo', 1.0]:
- # t = c.time()
- # serialized_data = self.serialize(data, mode=None)
- # c.print(serialized_data)
- # deserialized_data = self.deserialize(serialized_data)
- # assert deserialized_data == data, f"{deserialized_data} != {data}"
\ No newline at end of file
diff --git a/commune/modules/server/grpc/__init__.py b/commune/modules/server/grpc/__init__.py
deleted file mode 100755
index 0769c3359..000000000
--- a/commune/modules/server/grpc/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .serializer import Serializer
-from .client.client_module import Client
-from .server import Server
-from .interceptor import ServerInterceptor
-from .proto import server_pb2 as proto
-from .proto import server_pb2_grpc as grpc
diff --git a/commune/modules/server/grpc/client/grpc_client.py b/commune/modules/server/grpc/client/grpc_client.py
deleted file mode 100755
index 647ae99e5..000000000
--- a/commune/modules/server/grpc/client/grpc_client.py
+++ /dev/null
@@ -1,302 +0,0 @@
-from functools import partial
-
-from concurrent.futures import ThreadPoolExecutor
-import grpc
-import json
-import traceback
-import threading
-import uuid
-import sys
-import grpc
-from types import SimpleNamespace
-from typing import Tuple, List, Union
-from grpc import _common
-import sys
-import os
-import random
-import asyncio
-from copy import deepcopy
-import commune as c
-
-
-
-
-class Client(c.Module):
- """ Create and init the receptor object, which encapsulates a grpc connection to an axon endpoint
- """
-
- def __init__(
- self,
- ip: str ='0.0.0.0',
- port: int = 80 ,
- address: str = None,
- max_processes: int = 1,
- timeout:int = 4,
- loop: 'Loop' = None,
- key: 'Key' = None,
- network : 'Network' = c.default_network,
- stats = None,
- ):
- self.set_client(ip =ip,
- port = port ,
- max_processes = max_processes,
- timeout = timeout,
- loop = loop)
- self.key = key
- self.network = network
- self.set_stats(stats)
- self.serializer =c.module('serializer')
-
-
-
- def set_stats(self, stats=None):
- if stats is None:
- stats = {
- 'fn': {},
- 'count': 0,
- 'timestamp': c.time(),
- 'calls': 0,
- 'successes': 0,
- 'errors': 0,
-
-
- }
- assert isinstance(stats, dict), f"stats must be a dict, not {type(stats)}"
- self.stats = stats
- return stats
-
- def set_event_loop(self, loop: 'asyncio.EventLoop') -> None:
- try:
- loop = loop if loop else asyncio.get_event_loop()
- except RuntimeError as e:
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
-
- self.loop = loop
-
-
- def resolve_ip_and_port(self, ip, port) -> Tuple[str, int]:
- ip =ip if ip else self.default_ip
-
-
- if len(ip.split(":")) == 2:
- ip = ip.split(":")[0]
- port = int(ip.split(":")[1])
-
- assert isinstance(ip, str), f"ip must be a str, not {type(ip)}"
- assert isinstance(port, int), f"port must be an int, not {type(port)}"
-
- return ip, port
- def set_client(self,
- ip: str ='0.0.0.0',
- port: int = 80 ,
- max_processes: int = 1,
- timeout:int = 20,
- loop: 'asycnio.EventLoop' = None
- ):
- # if ip == c.external_ip():
- # ip = '0.0.0.0'
- from commune.module.server.proto import ServerStub
- # hopeful the only tuple i output, tehe
- if len(ip.split(":")) ==2:
- ip, port = ip.split(":")
- port = int(port)
- self.ip, self.port = self.resolve_ip_and_port(ip=ip, port=port)
- self.address = f"{self.ip}:{self.port}"
- self.set_event_loop(loop)
- channel = grpc.aio.insecure_channel(
- self.endpoint,
- options=[('grpc.max_send_message_length', -1),
- ('grpc.max_receive_message_length', -1),
- ('grpc.keepalive_time_ms', 100000)])
-
-
- stub = ServerStub( channel )
- self.channel = channel
- self.stub = stub
- self.client_uid = str(uuid.uuid1())
- self.semaphore = threading.Semaphore(max_processes)
- self.state_dict = _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY
- self.timeout = timeout
- self.timestamp = c.time()
-
-
- self.sync_the_async(loop=self.loop)
- self.success = False
-
- def get_server_info(self):
- self.server_info = self.forward(fn='info')
-
- @property
- def endpoint(self):
- return f"{self.ip}:{self.port}"
-
-
- def __call__(self, *args, return_future=False, **kwargs):
- future = self.async_forward(*args, **kwargs)
- if return_future:
- return future
- else:
-
- return self.loop.run_until_complete(future)
-
- def __str__ ( self ):
- return "Client({})".format(self.endpoint)
- def __repr__ ( self ):
- return self.__str__()
- def __del__ ( self ):
- try:
- result = self.channel._channel.check_connectivity_state(True)
- if self.state_dict[result] != self.state_dict[result].SHUTDOWN:
- loop = asyncio.get_event_loop()
- loop.run_until_complete ( self.channel.close() )
- except:
- pass
- def __exit__ ( self ):
- self.__del__()
-
- def nonce ( self ):
- import time as clock
- r"""creates a string representation of the time
- """
- return clock.monotonic_ns()
-
- def state ( self ):
- try:
- return self.state_dict[self.channel._channel.check_connectivity_state(True)]
- except ValueError:
- return "Channel closed"
-
- def close ( self ):
- self.__exit__()
-
- def sign(self):
- return 'signature'
-
- default_fn_stats = {'errors':0, 'calls':0, 'latency':0, 'latency_serial':0, 'latency_fn':0, 'latency_deserial':0}
- async def async_forward(
- self,
- data = None,
- metadata: dict = None,
- fn:str = None,
- args:list = None,
- kwargs:dict = None,
- timeout: int = None,
- results_only: bool = True,
- verbose: bool =False,
-
- **added_kwargs
- ) :
- if timeout == None:
- timeout = self.timeout
-
-
- kwargs = kwargs if kwargs else {}
- args = args if args else []
- data = data if data else {}
- metadata = metadata if metadata else {}
- if self.key :
- auth = self.auth(fn=fn, module=self.endpoint, key=self.key)
- else:
- auth = None
-
- data.update({
- 'fn' : fn,
- 'args' : list(args),
- 'kwargs': kwargs,
- 'auth' : auth,
- })
-
-
- data.update(kwargs)
-
- fn = data.get('fn', None)
- random_color = random.choice(['red','green','yellow','blue','magenta','cyan','white'])
- if verbose:
- c.print(f"SENDING --> {self.endpoint}::fn::({fn}), timeout: {timeout} data: {data}",color=random_color)
-
-
- fn_stats = self.stats['fn'].get(fn, self.default_fn_stats)
-
-
- try:
- # Serialize the request
- t = c.timer()
- grpc_request = self.serializer.serialize(data=data, metadata=metadata)
- fn_stats['latency_serial'] = t.seconds
-
- # Send the request
- t = c.timer()
- asyncio_future = self.stub.Forward(request = grpc_request, timeout = timeout)
- response = await asyncio_future
- fn_stats['latency_fn'] = t.seconds
-
- # Deserialize the responsex
- t.start()
- response = self.serializer.deserialize(response)
- fn_stats['latency_deserial'] = t.seconds
-
- # Update the stats
- fn_stats['latency'] = fn_stats['latency_serial'] + fn_stats['latency_fn'] + fn_stats['latency_deserial']
- fn_stats['calls'] = fn_stats.get('calls', 0) + 1
- fn_stats['last_called'] = self.time()
- self.stats['successes'] += 1
-
- except Exception as e:
- response = {'error': str(e)}
- fn_stats['errors'] = fn_stats['errors'] + 1
- self.stats['errors'] += 1
-
- if verbose:
- c.print(f"SUCCESS <-- {self.endpoint}::fn::({fn}), \n args:{args} \n kwargs:{kwargs} \n latency: {fn_stats['latency']} ",color=random_color)
-
- if results_only:
- response = response.get('data', {}).get('result', response)
-
- self.stats['calls'] += 1
- self.stats['last_called'] = c.time()
- self.stats['fn'][fn] = fn_stats
-
-
- return response
-
- async_call = async_forward
-
-
-
-
-
- def sync_the_async(self, loop = None):
- for f in dir(self):
- if 'async_' in f:
- setattr(self, f.replace('async_', ''), self.sync_wrapper(getattr(self, f), loop=loop))
-
- def sync_wrapper(self,fn:'asyncio.callable', loop = None) -> 'callable':
- '''
- Convert Async funciton to Sync.
-
- Args:
- fn (callable):
- An asyncio function.
-
- Returns:
- wrapper_fn (callable):
- Synchronous version of asyncio function.
- '''
- loop = loop if loop else self.loop
- def wrapper_fn(*args, **kwargs):
- return self.loop.run_until_complete(fn(*args, **kwargs))
- return wrapper_fn
-
- def test_module(self):
- module = Client(ip='0.0.0.0', port=8091)
- import torch
- data = {
- 'bro': torch.ones(10,10),
- 'fam': torch.zeros(10,10)
- }
-
- def virtual(self):
- return c.virtual_client(module = self)
-
-
diff --git a/commune/modules/server/grpc/client/grpc_client.yaml b/commune/modules/server/grpc/client/grpc_client.yaml
deleted file mode 100644
index d593a4616..000000000
--- a/commune/modules/server/grpc/client/grpc_client.yaml
+++ /dev/null
@@ -1 +0,0 @@
-network: null
diff --git a/commune/modules/server/grpc/client/pool/grpc_client_pool.py b/commune/modules/server/grpc/client/pool/grpc_client_pool.py
deleted file mode 100644
index eb1f710a9..000000000
--- a/commune/modules/server/grpc/client/pool/grpc_client_pool.py
+++ /dev/null
@@ -1,185 +0,0 @@
-""" Manages a pool of grpc connections as clients
-"""
-
-import math
-from typing import Tuple, List, Union
-from threading import Lock
-import streamlit as st
-import torch
-import asyncio
-from loguru import logger
-import concurrent
-import commune
-from concurrent.futures import ThreadPoolExecutor
-import commune
-
-class ClientPool (commune.Module):
- """ Manages a pool of grpc connections as clients
- """
- def __init__(
- self,
- modules,
- max_active_clients = 20,
-
- ):
-
- self.add_modules(modules)
- self.max_active_clients = self.max_active_clients
-
- self.client_stats = {}
- if modules == None:
- modules = self.modules()
- self.cull_mutex = Lock()
- self.total_requests = 0
-
-
- def __str__(self):
- return "ClientPool({},{})".format(len(self.clients), self.max_active_clients)
-
- def __repr__(self):
- return self.__str__()
-
- def __exit__(self):
- for client in self.clients:
- client.__del__()
-
- def forward (
- self,
- modules: List [str ] = None,
- args = None,
- kwargs = None,
- timeout: int,
- min_successes: int = None,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Forward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List[ bittensor.Endpoint ]` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of inputs. Tensors from x are sent forward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- TODO(const): Allow multiple tensors.
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- modality.
-
- timeout (int):
- Request timeout.
-
- Returns:
- forward_outputs (:obj:`List[ List[ torch.FloatTensor ]]` of shape :obj:`(num_endpoints * (num_synapses * (shape)))`, `required`):
- Output encodings of tensors produced by remote endpoints. Non-responses are zeroes of common shape.
-
- forward_codes (:obj:`List[ List[bittensor.proto.ReturnCodes] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call return ops.
-
- forward_times (:obj:`List[ List [float] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call times
- """
-
- loop = self.get_event_loop()
- return loop.run_until_complete (
- self.async_forward(kwargs=kwargs)
- )
-
-
- def add_module(self, module):
- if module in self.pool:
- return module
-
- self.pool[module] = commune.connect(module)
-
- async def async_forward (
- self,
- fn: None,
- module = None,
- args = None,
- kwargs = None,
- timeout: int = 2,
- min_successes: int = 2,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- # Init clients.
-
-
-
- client = await self.async_get_clients( module )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
- # Make calls.
- running_tasks = []
- for index, (client) in enumerate(clients.items()):
- args, kwargs = self.copy(args), self.copy(kwargs)
- task = asyncio.create_task(
- client.async_forward(*args, **kwargs)
- )
- running_tasks.append(task)
-
-
- outputs = []
-
- while len(running_tasks) > 0:
-
- finished_tasks, running_tasks = await asyncio.wait( running_tasks , return_when=asyncio.FIRST_COMPLETED)
- finished_tasks, running_tasks = list(finished_tasks), list(running_tasks)
-
- responses = await asyncio.gather(*finished_tasks)
-
- for response in responses:
- if min_successes > 0:
- if response[1][0] == 1:
- outputs.append( response )
- if len(outputs) >= min_successes :
- # cancel the rest of the tasks
- [t.cancel() for t in running_tasks]
- running_tasks = [t for t in running_tasks if t.cancelled()]
- assert len(running_tasks) == 0, f'{len(running_tasks)}'
- break
- else:
-
- outputs.append( response)
-
- return outputs
-
-
-
-
- def check_clients( self ):
- r""" Destroys clients based on QPS until there are no more than max_active_clients.
- """
- with self.cull_mutex:
- # ---- Finally: Kill clients over max allowed ----
- if len(self.clients) > self.max_active_clients:
- c = list(self.clients.keys())[0]
- self.clients.pop(c, None)
-
-
-
- async def async_get_client( self,
- module = None,
- timeout=1 ) -> 'commune.Client':
- r""" Finds or creates a client TCP connection associated with the passed Neuron Endpoint
- Returns
- client: (`commune.Client`):
- client with tcp connection endpoint at endpoint.ip:endpoint.port
- """
- # ---- Find the active client for this endpoint ----
-
- modules = self.modules(module)
-
-
- if module == None:
- client = self.choice(self.clients.values())
- if module in self.clients :
- client = self.clients[module]
- else:
- client = await self.async_connect(module, timeout=timeout)
- self.clients[ client.endpoint.hotkey ] = client
-
- return client
-
diff --git a/commune/modules/server/grpc/client/pool/grpc_client_pool.yaml b/commune/modules/server/grpc/client/pool/grpc_client_pool.yaml
deleted file mode 100644
index a09e9e9c2..000000000
--- a/commune/modules/server/grpc/client/pool/grpc_client_pool.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-max_active_clients: 100
-modules: dataset
-max_staleness: 10
diff --git a/commune/modules/server/grpc/client/pool/pool.py b/commune/modules/server/grpc/client/pool/pool.py
deleted file mode 100644
index e7b4cf33a..000000000
--- a/commune/modules/server/grpc/client/pool/pool.py
+++ /dev/null
@@ -1,190 +0,0 @@
-""" Manages a pool of grpc connections as modules
-"""
-
-import math
-from typing import Tuple, List, Union
-from threading import Lock
-import streamlit as st
-import asyncio
-from loguru import logger
-import concurrent
-import commune
-from concurrent.futures import ThreadPoolExecutor
-import commune as c
-import asyncio
-
-class ModulePool (c.Module):
- """ Manages a pool of grpc connections as modules
- """
-
-
-
- def __init__(
- self,
- modules = None,
- max_modules:int = 20,
- stats = None,
-
- ):
- self.cull_mutex = Lock()
- self.modules = {}
- self.max_modules = max_modules
- self.add_modules(modules)
- self.set_stats(stats)
- self.total_requests = 0
-
-
- def set_stats(self, stats=None):
- if stats == None:
- stats = self.munch({})
- self.stats = stats
- return stats
- def add_module(self, *args, **kwargs)-> str:
- loop = self.get_event_loop()
- return loop.run_until_complete(self.async_add_module( *args, **kwargs))
-
- async def async_add_module(self, module:str = None, timeout=3)-> str:
- print(module)
- self.modules[module] = await c.async_connect(module, timeout=timeout,virtual=False)
- return self.modules[module]
-
-
- def add_modules(self, modules:list):
- if modules == None:
- modules = c.servers()
- if isinstance(modules, str):
- modules = c.servers(modules)
- loop = self.get_event_loop()
- return loop.run_until_complete(asyncio.gather(*[self.async_add_module(m) for m in modules]))
-
-
-
- def has_module(self, module:str)->bool:
- return bool(module in self.modules)
-
- def get_module(self, *args, **kwargs):
- loop = self.get_event_loop()
- return loop.run_until_complete(self.async_get_module(*args, **kwargs))
-
-
-
-
- async def async_get_module( self,
- module = None,
- timeout=1,
- retrials=2) -> 'c.Client':
-
- if module == None:
- module = c.choice(list(self.modules.values()))
- elif isinstance(modules, str):
- if module in self.modules :
- module = self.modules[module]
- else:
- module = await self.async_add_module(module)
- else:
- raise NotImplemented(module)
-
- return module
-
-
-
- def __str__(self):
- return "ModulePool({},{})".format(len(self.modules), self.max_modules)
-
- def __repr__(self):
- return self.__str__()
-
- # def __exit__(self):
- # for module in self.modules:
- # module.__del__()
-
- def forward (self, *args, **kwargs) :
-
- loop = self.get_event_loop()
- return loop.run_until_complete (self.async_forward(*args, **kwargs) )
-
-
- async def async_forward (
- self,
- fn:str,
- args:list = None,
- kwargs:dict = None,
- module:list = None,
- timeout: int = 2,
- ) :
- # Init modules.
-
-
-
- module = await self.async_get_module( module )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
- result = await module.async_forward(fn=fn, args=args, kwargs=kwargs, timeout=timeout)
-
-
-
- return result
-
-
- async def async_forward_pool (
- self,
- fn:str,
- args:list = None,
- kwargs:dict = None,
- modules:list = None,
- timeout: int = 2,
- min_successes: int = 2,
- ) :
- # Init modules.
-
-
-
- module = await self.async_get_module( modules )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
-
- outputs = []
-
- while len(running_tasks) > 0:
-
- finished_tasks, running_tasks = await asyncio.wait( running_tasks , return_when=asyncio.FIRST_COMPLETED)
- finished_tasks, running_tasks = list(finished_tasks), list(running_tasks)
-
- responses = await asyncio.gather(*finished_tasks)
-
- for response in responses:
- if min_successes > 0:
- if response[1][0] == 1:
- outputs.append( response )
- if len(outputs) >= min_successes :
- # cancel the rest of the tasks
- [t.cancel() for t in running_tasks]
- running_tasks = [t for t in running_tasks if t.cancelled()]
- assert len(running_tasks) == 0, f'{len(running_tasks)}'
- break
- else:
-
- outputs.append( response)
-
- return outputs
-
- @classmethod
- def test(cls, **kwargs):
- self = cls(modules='module')
- t = c.time()
- for i in range(10):
- print(i)
- output = self.forward('namespace')
- cls.print(output)
-
- cls.print('time', c.time() - t)
-
-
-if __name__ == '__main__':
- ModulePool.run()
\ No newline at end of file
diff --git a/commune/modules/server/grpc/grpc_server.py b/commune/modules/server/grpc/grpc_server.py
deleted file mode 100755
index b2b2c0b6c..000000000
--- a/commune/modules/server/grpc/grpc_server.py
+++ /dev/null
@@ -1,518 +0,0 @@
-import argparse
-import os
-import copy
-import inspect
-import time
-from concurrent import futures
-from typing import Dict, List, Callable, Optional, Tuple, Union
-import sys
-import torch
-import grpc
-from substrateinterface import Keypair
-from loguru import logger
-import sys
-import os
-import asyncio
-import commune as c
-from commune.modules.server.grpc.interceptor import ServerInterceptor
-from commune.modules.server.grpc.serializer import Serializer
-from commune.modules.server.grpc.proto import ServerServicer
-from commune.modules.server.grpc.proto import DataBlock
-import signal
-from munch import Munch
-
-
-class Server(ServerServicer, Serializer, c.Module):
- """ The factory class for commune.Server object
- The Server is a grpc server for the commune network which opens up communication between it and other neurons.
- The server protocol is defined in commune.proto and describes the manner in which forward and backwards requests
- are transported / encoded between validators and servers
- """
- port_range = [50050, 50100]
- default_ip = '0.0.0.0'
-
- def __init__(
- self,
- module: Union[c.Module, object]= None,
- name = None,
- ip: Optional[str] = None,
- port: Optional[int] = None,
- max_workers: Optional[int] = 10,
- authenticate = False,
- maximum_concurrent_rpcs: Optional[int] = 400,
- thread_pool: Optional[futures.ThreadPoolExecutor] = None,
- timeout: Optional[int] = None,
- compression:Optional[str] = None,
- server: Optional['grpc._Server'] = None,
- verbose: bool = True,
- whitelist: List[str] = None,
- blacklist: List[str ] = None,
- loop: 'asyncio.Loop' = None,
- exceptions_to_raise = ['CUDA out of memory', 'PYTORCH_CUDA_ALLOC_CONF'],
- network: 'Network' = None,
-
-
- ) -> 'Server':
- r""" Creates a new commune.Server object from passed arguments.
- Args:
- thread_pool (:obj:`Optional[ThreadPoolExecutor]`, `optional`):
- Threadpool used for processing server queries.
- server (:obj:`Optional[grpc._Server]`, `required`):
- Grpc server endpoint, overrides passed threadpool.
- port (:type:`Optional[int]`, `optional`):
- Binding port.
- ip (:type:`Optional[str]`, `optional`):
- Binding ip.
- external_ip (:type:`Optional[str]`, `optional`):
- The external ip of the server to broadcast to the network.
- max_workers (:type:`Optional[int]`, `optional`):
- Used to create the threadpool if not passed, specifies the number of active threads servicing requests.
- maximum_concurrent_rpcs (:type:`Optional[int]`, `optional`):
- Maximum allowed concurrently processed RPCs.
- timeout (:type:`Optional[int]`, `optional`):
- timeout on the forward requests.
- authenticate (:type:`Optional[bool]`, `optional`):
- Whether or not to authenticate the server.
-
- """
-
-
-
- self.set_event_loop(loop)
-
-
- if name == None:
- if not hasattr(module, 'module_name'):
- name = str(module)
- self.name = name
- self.timeout = timeout
- self.verbose = verbose
- self.module = module
- self.authenticate = authenticate
-
-
- self.ip = ip = ip if ip != None else self.default_ip
- self.port = port = c.resolve_port(port)
- while not self.port_available(ip=ip, port=port):
- port = self.get_available_port(ip=ip)
- is_port_available = self.port_available(ip=ip, port=port)
-
- self.thread_pool = self.set_thread_pool(thread_pool=thread_pool)
-
-
- server = grpc.server( self.thread_pool,
- # interceptors=(ServerInterceptor(blacklist=blacklist,receiver_hotkey=self.wallet.hotkey.ss58_address),),
- maximum_concurrent_rpcs = maximum_concurrent_rpcs,
- options = [('grpc.keepalive_time_ms', 100000),
- ('grpc.keepalive_timeout_ms', 500000)]
- )
-
- # set the server compression algorithm
- self.server = server
- from commune.modules.server.grpc.proto import add_ServerServicer_to_server
- add_ServerServicer_to_server( self, server )
- self.full_address = str( ip ) + ":" + str( port )
- self.server.add_insecure_port( self.full_address )
-
- self.ip = c.external_ip()
- self.port = port
-
- # whether or not the server is running
- self.started = False
- self.set_stats()
-
- self.exceptions_to_raise = exceptions_to_raise
- self.set_module_info()
- def set_event_loop(self, loop: 'asyncio.AbstractEventLoop' = None) -> None:
- if loop == None:
- loop = c.get_event_loop()
- self.loop = loop
-
- def set_whitelist(self, functions: List[str]):
- if functions == None:
- functions = []
- self.whitelist = list(set(functions + c.helper_functions))
-
- def set_module_info(self):
- self.module_info = self.module.info()
- self.allowed_functions = self.module_info['functions']
- self.allowed_attributes = self.module_info['attributes']
-
-
- def check_call(self, fn:str, args:list, kwargs:dict, user:dict):
- passed = False
-
- if fn == 'getattr':
- if len(args) == 1:
- attribute = args[0]
- elif 'k' in kwargs:
- attribute = kwargs['k']
- else:
- raise Exception('you are falling {k} which is an attribute that is invalid')
-
- # is it an allowed attribute
- if attribute in self.allowed_attributes:
- passed = True
- else:
-
- if fn in self.allowed_functions:
- passed = True
-
-
-
-
-
-
-
- {'passed': False}
-
- def set_thread_pool(self, thread_pool: 'ThreadPoolExecutor' = None, max_workers: int = 10) -> 'ThreadPoolExecutor':
- if thread_pool == None:
- thread_pool = futures.ThreadPoolExecutor(max_workers=max_workers)
-
- self.thread_pool = thread_pool
- return thread_pool
-
-
-
-
-
- @classmethod
- def help(cls):
- """ Print help to stdout
- """
- parser = argparse.ArgumentParser()
- cls.add_args( parser )
- print (cls.__new__.__doc__)
- parser.print_help()
-
-
- def __str__(self) -> str:
- return "Server({}, {}, {})".format( self.ip, self.port, "started" if self.started else "stopped")
-
- def __repr__(self) -> str:
- return self.__str__()
-
-
-
- def set_stats(self):
- self.stats = dict(
- call_count = 0,
- total_bytes = 0,
- time = {}
- )
-
- def __call__(self,
- data:dict = None,
- metadata:dict = None,
- verbose: bool = True,):
- data = data if data else {}
- metadata = metadata if metadata else {}
- output_data = {}
-
-
- t = c.timer()
- success = False
-
- fn = data['fn']
- kwargs = data.get('kwargs', {})
- args = data.get('args', [])
- user = data.get('user', [])
- auth = data.get('auth', None)
- if auth != None:
- c.print(auth)
- try:
-
- self.check_call(fn=fn, args=args, kwargs=kwargs, user=user)
-
- c.print('Calling Function: '+fn, color='cyan')
- fn_obj = getattr(self.module, fn)
-
- if callable(fn_obj):
- # if the function is callable (an actual function)
- output_data = fn_obj(*args, **kwargs)
- else:
- # if the function is an attribute
- output_data = fn_obj
-
- success = True
-
- except RuntimeError as ex:
- c.print(f'Exception in server: {ex}', color= 'red')
- if "There is no current event loop in thread" in str(ex):
- if verbose:
- c.print(f'SETTING NEW ANSYNCIO LOOP', color='yellow')
- self.loop = asyncio.new_event_loop()
- asyncio.set_event_loop(self.loop)
- return self.__call__(data=data, metadata=metadata)
-
- except Exception as ex:
- output_data = str(ex)
- if any([rex in output_data for rex in self.exceptions_to_raise]):
- raise(ex)
- self.stop()
-
- if verbose:
- c.print(f'[bold]EXCEPTION[/bold]: {ex}', color='red')
-
-
- sample_info ={
- 'latency': t.seconds,
- 'in_bytes': sys.getsizeof(data),
- 'out_bytes': sys.getsizeof(output_data),
- 'user': data.get('user', {}),
- 'fn': fn,
- 'timestamp': c.time(),
- 'success': success
- }
-
- # calculate bps (bytes per second) for upload and download
- sample_info['upload_bps'] = sample_info['in_bytes'] / sample_info['latency']
- sample_info['download_bps'] = sample_info['out_bytes'] / sample_info['latency']
-
- c.print(sample_info)
- self.log_sample(sample_info)
-
-
-
- return {'data': {'result': output_data, 'info': sample_info }, 'metadata': metadata}
-
-
- def log_sample(self, sample_info: dict, max_history: int = 100) -> None:
- if not hasattr(self, 'stats'):
- self.stats = {}
-
-
- sample_info['success'] = True
-
- self.stats['successes'] = self.stats.get('success', 0) + (1 if sample_info['success'] else 0)
- self.stats['errors'] = self.stats.get('errors', 0) + (1 if not sample_info['success'] else 0)
- self.stats['requests'] = self.stats.get('requests', 0) + 1
- self.stats['history'] = self.stats.get('history', []) + [sample_info]
- self.stats['most_recent'] = sample_info
-
-
- if len(self.stats['history']) > max_history:
- self.stats['history'].pop(0)
-
- def Forward(self, request: DataBlock, context: grpc.ServicerContext) -> DataBlock:
- r""" The function called by remote GRPC Forward requests. The Datablock is a generic formatter.
-
- Args:
- request (:obj:`DataBlock`, `required`):
- Tensor request proto.
- context (:obj:`grpc.ServicerContext`, `required`):
- grpc server context.
-
- Returns:
- response (c.proto.DataBlock):
- proto response carring the nucleus forward output or None under failure.
- """
-
-
-
-
-
- deserialize_timer = c.timer()
- request = self.deserialize(request)
- self.stats['time']['deserialize'] = deserialize_timer.seconds
-
- forward_timer = c.timer()
- response = self(**request)
- self.stats['time']['module'] = forward_timer.seconds
-
- serializer_timer = c.timer()
- response = self.serialize(**response)
- self.stats['time']['serialize'] = serializer_timer.seconds
- return response
-
- def __del__(self):
- r""" Called when this axon is deleted, ensures background threads shut down properly.
- """
- c.print('deregister')
- c.deregister_server(name=self.name)
- if hasattr(self, 'server'):
- self.stop()
-
-
-
-
- @property
- def id(self) -> str:
- return f'{self.__class__.name}(endpoint={self.endpoint}, model={self.model_name})'
-
-
- @classmethod
- def argparse(cls):
- parser = argparse.ArgumentParser(description='Gradio API and Functions')
- parser.add_argument('-fn', '--function', dest='function', help='run a function from the module', type=str, default="streamlit")
- parser.add_argument('-kwargs', '--kwargs', dest='kwargs', help='arguments to the function', type=str, default="{}")
- parser.add_argument('-args', '--args', dest='args', help='arguments to the function', type=str, default="[]")
- return parser.parse_args()
-
-
- @classmethod
- def run(cls):
- input_args = cls.argparse()
- assert hasattr(cls, input_args.function)
- kwargs = json.loads(input_args.kwargs)
- assert isinstance(kwargs, dict)
-
- args = json.loads(input_args.args)
- assert isinstance(args, list)
- getattr(cls, input_args.function)(*args, **kwargs)
-
- @property
- def endpoint(self):
- return f'{self.ip}:{self.port}'
-
- @property
- def address(self):
- return f'{self.ip}:{self.port}'
-
-
-
- def serve(self,
- wait_for_termination:bool=False,
- update_period:int = 10,
- verbose:bool= True,
- register:bool=True):
- '''
- Serve the server and loop it until termination.
- '''
- self.start(wait_for_termination=False)
-
- lifetime_seconds:int = 0
-
- def print_serve_status():
- text = f'{str(self.module.server_name)} IP::{self.endpoint} LIFETIME(s): {lifetime_seconds}s'
- c.print(text, color='green')
-
-
- # register the server
- if register:
- c.register_server(name=self.name,
- ip=self.ip,
- port=self.port)
-
-
-
-
- try:
- while True:
- if not wait_for_termination:
- break
- lifetime_seconds += update_period
- if verbose:
- print_serve_status()
-
- time.sleep(update_period)
-
- except Exception as e:
- c.deregister_server(name=self.name)
- raise e
-
-
-
-
-
-
-
-
- def start(self, wait_for_termination=False) -> 'Server':
- r""" Starts the standalone axon GRPC server thread.
- """
- if self.server != None:
- self.server.stop( grace = 1 )
- logger.success("Server Stopped:".ljust(20) + "{}", self.ip + ':' + str(self.port))
-
- self.server.start()
- logger.success("Server Started:".ljust(20) + "{}", self.ip + ':' + str(self.port))
- self.started = True
- if wait_for_termination:
- self.server.wait_for_termination()
-
- return self
-
-
- def stop(self) -> 'Server':
- r""" Stop the axon grpc server.
- """
- c.deregister_server(name=self.name)
- if self.server != None:
- print('stopping server', self.server.__dict__)
- self.server.stop( grace = 1 )
- logger.success("Server Stopped:".ljust(20) + "{}", self.ip + ':' + str(self.port))
- self.started = False
-
-
- return self
-
- @staticmethod
- def kill_port(port:int)-> str:
- from psutil import process_iter
- '''
- Kills the port {port}
- '''
- for proc in process_iter():
- for conns in proc.connections(kind='inet'):
- if conns.laddr.port == port:
- proc.send_signal(signal.SIGKILL) # or SIGKILL
- return port
-
-
- @classmethod
- def get_used_ports(cls, port_range: List[int] = None , ip:str =None) -> int:
- port_range = port_range if port_range else cls.port_range
- ip = ip if ip else cls.default_ip
- used_ports = []
- # return only when the port is available
- for port in range(*port_range):
- if not cls.port_available(port=port, ip=ip):
- used_ports.append(port)
- return used_ports
-
-
-
- @classmethod
- def port_available(cls, port:int, ip:str = None):
- '''
- checks if a port is available
- '''
-
- return not c.port_used(port=port, ip=ip)
-
- @classmethod
- def test_server(cls):
-
- class DemoModule:
- def __call__(self, data:dict, metadata:dict) -> dict:
- return {'data': data, 'metadata': {}}
-
- modules = {}
- for m in range(10):
- module = Server(module=DemoModule())
- # module.start()
- modules[module.port] = module
-
-
- c.Client()
- module.stop()
-
-
- @property
- def info(self):
- '''
- Any server info
- '''
- return dict(
- ip=self.ip,
- port= self.port,
- address = self.endpoint,
- whitelist=self.whitelist,
- blacklist=self.blacklist,
- )
-
-
-
-
\ No newline at end of file
diff --git a/commune/modules/server/grpc/grpc_server.yaml b/commune/modules/server/grpc/grpc_server.yaml
deleted file mode 100755
index b680e5d76..000000000
--- a/commune/modules/server/grpc/grpc_server.yaml
+++ /dev/null
@@ -1,518 +0,0 @@
-import argparse
-import os
-import copy
-import inspect
-import time
-from concurrent import futures
-from typing import Dict, List, Callable, Optional, Tuple, Union
-import sys
-import torch
-import grpc
-from substrateinterface import Keypair
-from loguru import logger
-import sys
-import os
-import asyncio
-import commune as c
-from commune.modules.server.grpc.interceptor import ServerInterceptor
-from commune.modules.server.grpc.serializer import Serializer
-from commune.modules.server.grpc.proto import ServerServicer
-from commune.modules.server.grpc.proto import DataBlock
-import signal
-from munch import Munch
-
-
-class Server(ServerServicer, Serializer, c.Module):
- """ The factory class for commune.Server object
- The Server is a grpc server for the commune network which opens up communication between it and other neurons.
- The server protocol is defined in commune.proto and describes the manner in which forward and backwards requests
- are transported / encoded between validators and servers
- """
- port_range = [50050, 50100]
- default_ip = '0.0.0.0'
-
- def __init__(
- self,
- module: Union[c.Module, object]= None,
- name = None,
- ip: Optional[str] = None,
- port: Optional[int] = None,
- max_workers: Optional[int] = 10,
- authenticate = False,
- maximum_concurrent_rpcs: Optional[int] = 400,
- thread_pool: Optional[futures.ThreadPoolExecutor] = None,
- timeout: Optional[int] = None,
- compression:Optional[str] = None,
- server: Optional['grpc._Server'] = None,
- verbose: bool = True,
- whitelist: List[str] = None,
- blacklist: List[str ] = None,
- loop: 'asyncio.Loop' = None,
- exceptions_to_raise = ['CUDA out of memory', 'PYTORCH_CUDA_ALLOC_CONF'],
- network: 'Network' = None,
-
-
- ) -> 'Server':
- r""" Creates a new commune.Server object from passed arguments.
- Args:
- thread_pool (:obj:`Optional[ThreadPoolExecutor]`, `optional`):
- Threadpool used for processing server queries.
- server (:obj:`Optional[grpc._Server]`, `required`):
- Grpc server endpoint, overrides passed threadpool.
- port (:type:`Optional[int]`, `optional`):
- Binding port.
- ip (:type:`Optional[str]`, `optional`):
- Binding ip.
- external_ip (:type:`Optional[str]`, `optional`):
- The external ip of the server to broadcast to the network.
- max_workers (:type:`Optional[int]`, `optional`):
- Used to create the threadpool if not passed, specifies the number of active threads servicing requests.
- maximum_concurrent_rpcs (:type:`Optional[int]`, `optional`):
- Maximum allowed concurrently processed RPCs.
- timeout (:type:`Optional[int]`, `optional`):
- timeout on the forward requests.
- authenticate (:type:`Optional[bool]`, `optional`):
- Whether or not to authenticate the server.
-
- """
-
-
-
- self.set_event_loop(loop)
-
-
- if name == None:
- if not hasattr(module, 'module_name'):
- name = str(module)
- self.name = name
- self.timeout = timeout
- self.verbose = verbose
- self.module = module
- self.authenticate = authenticate
-
-
- self.ip = ip = ip if ip != None else self.default_ip
- self.port = port = c.resolve_port(port)
- while not self.port_available(ip=ip, port=port):
- port = self.get_available_port(ip=ip)
- is_port_available = self.port_available(ip=ip, port=port)
-
- self.thread_pool = self.set_thread_pool(thread_pool=thread_pool)
-
-
- server = grpc.server( self.thread_pool,
- # interceptors=(ServerInterceptor(blacklist=blacklist,receiver_hotkey=self.wallet.hotkey.ss58_address),),
- maximum_concurrent_rpcs = maximum_concurrent_rpcs,
- options = [('grpc.keepalive_time_ms', 100000),
- ('grpc.keepalive_timeout_ms', 500000)]
- )
-
- # set the server compression algorithm
- self.server = server
- from commune.modules.server.grpc.proto import add_ServerServicer_to_server
- add_ServerServicer_to_server( self, server )
- self.full_address = str( ip ) + ":" + str( port )
- self.server.add_insecure_port( self.full_address )
-
- self.ip = c.external_ip()
- self.port = port
-
- # whether or not the server is running
- self.started = False
- self.set_stats()
-
- self.exceptions_to_raise = exceptions_to_raise
- self.set_module_info()
- def set_event_loop(self, loop: 'asyncio.AbstractEventLoop' = None) -> None:
- if loop == None:
- loop = c.get_event_loop()
- self.loop = loop
-
- def set_whitelist(self, functions: List[str]):
- if functions == None:
- functions = []
- self.whitelist = list(set(functions + c.helper_functions))
-
- def set_module_info(self):
- self.module_info = self.module.info()
- self.allowed_functions = self.module_info['functions']
- self.allowed_attributes = self.module_info['attributes']
-
-
- def check_call(self, fn:str, args:list, kwargs:dict, user:dict):
- passed = False
-
- if fn == 'getattr':
- if len(args) == 1:
- attribute = args[0]
- elif 'k' in kwargs:
- attribute = kwargs['k']
- else:
- raise Exception('you are falling {k} which is an attribute that is invalid')
-
- # is it an allowed attribute
- if attribute in self.allowed_attributes:
- passed = True
- else:
-
- if fn in self.allowed_functions:
- passed = True
-
-
-
-
-
-
-
- {'passed': False}
-
- def set_thread_pool(self, thread_pool: 'ThreadPoolExecutor' = None, max_workers: int = 10) -> 'ThreadPoolExecutor':
- if thread_pool == None:
- thread_pool = futures.ThreadPoolExecutor(max_workers=max_workers)
-
- self.thread_pool = thread_pool
- return thread_pool
-
-
-
-
-
- @classmethod
- def help(cls):
- """ Print help to stdout
- """
- parser = argparse.ArgumentParser()
- cls.add_args( parser )
- print (cls.__new__.__doc__)
- parser.print_help()
-
-
- def __str__(self) -> str:
- return "Server({}, {}, {})".format( self.ip, self.port, "started" if self.started else "stopped")
-
- def __repr__(self) -> str:
- return self.__str__()
-
-
-
- def set_stats(self):
- self.stats = dict(
- call_count = 0,
- total_bytes = 0,
- time = {}
- )
-
- def __call__(self,
- data:dict = None,
- metadata:dict = None,
- verbose: bool = True,):
- data = data if data else {}
- metadata = metadata if metadata else {}
- output_data = {}
-
-
- t = c.timer()
- success = False
-
- fn = data['fn']
- kwargs = data.get('kwargs', {})
- args = data.get('args', [])
- user = data.get('user', [])
- auth = data.get('auth', None)
- if auth != None:
- c.print(auth)
- try:
-
- self.check_call(fn=fn, args=args, kwargs=kwargs, user=user)
-
- c.print('Calling Function: '+fn, color='cyan')
- fn_obj = getattr(self.module, fn)
-
- if callable(fn_obj):
- # if the function is callable (an actual function)
- output_data = fn_obj(*args, **kwargs)
- else:
- # if the function is an attribute
- output_data = fn_obj
-
- success = True
-
- except RuntimeError as ex:
- c.print(f'Exception in server: {ex}', color= 'red')
- if "There is no current event loop in thread" in str(ex):
- if verbose:
- c.print(f'SETTING NEW ANSYNCIO LOOP', color='yellow')
- self.loop = asyncio.new_event_loop()
- asyncio.set_event_loop(self.loop)
- return self.__call__(data=data, metadata=metadata)
-
- except Exception as ex:
- output_data = str(ex)
- if any([rex in output_data for rex in self.exceptions_to_raise]):
- raise(ex)
- self.stop()
-
- if verbose:
- c.print(f'[bold]EXCEPTION[/bold]: {ex}', color='red')
-
-
- sample_info ={
- 'latency': t.seconds,
- 'in_bytes': sys.getsizeof(data),
- 'out_bytes': sys.getsizeof(output_data),
- 'user': data.get('user', {}),
- 'fn': fn,
- 'timestamp': c.time(),
- 'success': success
- }
-
- # calculate bps (bytes per second) for upload and download
- sample_info['upload_bps'] = sample_info['in_bytes'] / sample_info['latency']
- sample_info['download_bps'] = sample_info['out_bytes'] / sample_info['latency']
-
- c.print(sample_info)
- self.log_sample(sample_info)
-
-
-
- return {'data': {'result': output_data, 'info': sample_info }, 'metadata': metadata}
-
-
- def log_sample(self, sample_info: dict, max_history: int = 100) -> None:
- if not hasattr(self, 'stats'):
- self.stats = {}
-
-
- sample_info['success'] = True
-
- self.stats['successes'] = self.stats.get('success', 0) + (1 if sample_info['success'] else 0)
- self.stats['errors'] = self.stats.get('errors', 0) + (1 if not sample_info['success'] else 0)
- self.stats['requests'] = self.stats.get('requests', 0) + 1
- self.stats['history'] = self.stats.get('history', []) + [sample_info]
- self.stats['most_recent'] = sample_info
-
-
- if len(self.stats['history']) > max_history:
- self.stats['history'].pop(0)
-
- def Forward(self, request: DataBlock, context: grpc.ServicerContext) -> DataBlock:
- r""" The function called by remote GRPC Forward requests. The Datablock is a generic formatter.
-
- Args:
- request (:obj:`DataBlock`, `required`):
- Tensor request proto.
- context (:obj:`grpc.ServicerContext`, `required`):
- grpc server context.
-
- Returns:
- response (c.proto.DataBlock):
- proto response carring the nucleus forward output or None under failure.
- """
-
-
-
-
-
- deserialize_timer = c.timer()
- request = self.deserialize(request)
- self.stats['time']['deserialize'] = deserialize_timer.seconds
-
- forward_timer = c.timer()
- response = self(**request)
- self.stats['time']['module'] = forward_timer.seconds
-
- serializer_timer = c.timer()
- response = self.serialize(**response)
- self.stats['time']['serialize'] = serializer_timer.seconds
- return response
-
- def __del__(self):
- r""" Called when this axon is deleted, ensures background threads shut down properly.
- """
- c.print('deregister')
- c.deregister_server(name=self.name)
- if hasattr(self, 'server'):
- self.stop()
-
-
-
-
- @property
- def id(self) -> str:
- return f'{self.__class__.name}(endpoint={self.endpoint}, model={self.model_name})'
-
-
- @classmethod
- def argparse(cls):
- parser = argparse.ArgumentParser(description='Gradio API and Functions')
- parser.add_argument('-fn', '--function', dest='function', help='run a function from the module', type=str, default="streamlit")
- parser.add_argument('-kwargs', '--kwargs', dest='kwargs', help='arguments to the function', type=str, default="{}")
- parser.add_argument('-args', '--args', dest='args', help='arguments to the function', type=str, default="[]")
- return parser.parse_args()
-
-
- @classmethod
- def run(cls):
- input_args = cls.argparse()
- assert hasattr(cls, input_args.function)
- kwargs = json.loads(input_args.kwargs)
- assert isinstance(kwargs, dict)
-
- args = json.loads(input_args.args)
- assert isinstance(args, list)
- getattr(cls, input_args.function)(*args, **kwargs)
-
- @property
- def endpoint(self):
- return f'{self.ip}:{self.port}'
-
- @property
- def address(self):
- return f'{self.ip}:{self.port}'
-
-
-
- def serve(self,
- wait_for_termination:bool=False,
- update_period:int = 10,
- verbose:bool= True,
- register:bool=True):
- '''
- Serve the server and loop it until termination.
- '''
- self.start(wait_for_termination=False)
-
- lifetime_seconds:int = 0
-
- def print_serve_status():
- text = f'{str(self.module.module_name)} IP::{self.endpoint} LIFETIME(s): {lifetime_seconds}s'
- c.print(text, color='green')
-
-
- # register the server
- if register:
- c.register_server(name=self.name,
- ip=self.ip,
- port=self.port)
-
-
-
-
- try:
- while True:
- if not wait_for_termination:
- break
- lifetime_seconds += update_period
- if verbose:
- print_serve_status()
-
- time.sleep(update_period)
-
- except Exception as e:
- c.deregister_server(name=self.name)
- raise e
-
-
-
-
-
-
-
-
- def start(self, wait_for_termination=False) -> 'Server':
- r""" Starts the standalone axon GRPC server thread.
- """
- if self.server != None:
- self.server.stop( grace = 1 )
- logger.success("Server Stopped:".ljust(20) + "{}", self.ip + ':' + str(self.port))
-
- self.server.start()
- logger.success("Server Started:".ljust(20) + "{}", self.ip + ':' + str(self.port))
- self.started = True
- if wait_for_termination:
- self.server.wait_for_termination()
-
- return self
-
-
- def stop(self) -> 'Server':
- r""" Stop the axon grpc server.
- """
- c.deregister_server(name=self.name)
- if self.server != None:
- print('stopping server', self.server.__dict__)
- self.server.stop( grace = 1 )
- logger.success("Server Stopped:".ljust(20) + "{}", self.ip + ':' + str(self.port))
- self.started = False
-
-
- return self
-
- @staticmethod
- def kill_port(port:int)-> str:
- from psutil import process_iter
- '''
- Kills the port {port}
- '''
- for proc in process_iter():
- for conns in proc.connections(kind='inet'):
- if conns.laddr.port == port:
- proc.send_signal(signal.SIGKILL) # or SIGKILL
- return port
-
-
- @classmethod
- def get_used_ports(cls, port_range: List[int] = None , ip:str =None) -> int:
- port_range = port_range if port_range else cls.port_range
- ip = ip if ip else cls.default_ip
- used_ports = []
- # return only when the port is available
- for port in range(*port_range):
- if not cls.port_available(port=port, ip=ip):
- used_ports.append(port)
- return used_ports
-
-
-
- @classmethod
- def port_available(cls, port:int, ip:str = None):
- '''
- checks if a port is available
- '''
-
- return not c.port_used(port=port, ip=ip)
-
- @classmethod
- def test_server(cls):
-
- class DemoModule:
- def __call__(self, data:dict, metadata:dict) -> dict:
- return {'data': data, 'metadata': {}}
-
- modules = {}
- for m in range(10):
- module = Server(module=DemoModule())
- # module.start()
- modules[module.port] = module
-
-
- c.Client()
- module.stop()
-
-
- @property
- def info(self):
- '''
- Any server info
- '''
- return dict(
- ip=self.ip,
- port= self.port,
- address = self.endpoint,
- whitelist=self.whitelist,
- blacklist=self.blacklist,
- )
-
-
-
-
\ No newline at end of file
diff --git a/commune/modules/server/grpc/interceptor.py b/commune/modules/server/grpc/interceptor.py
deleted file mode 100755
index f69102ff5..000000000
--- a/commune/modules/server/grpc/interceptor.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import argparse
-import os
-import copy
-import inspect
-import time
-from concurrent import futures
-from typing import Dict, List, Callable, Optional, Tuple, Union
-
-import torch
-import grpc
-from substrateinterface import Keypair
-
-
-
-
-class ServerInterceptor(grpc.ServerInterceptor):
- """Creates a new server interceptor that authenticates incoming messages from passed arguments."""
-
- def __init__(
- self,
- receiver_hotkey: str,
- blacklist: Callable = None,
- ):
- r"""Creates a new server interceptor that authenticates incoming messages from passed arguments.
- Args:
- receiver_hotkey(str):
- the SS58 address of the hotkey which should be targeted by RPCs
- black_list (Function, `optional`):
- black list function that prevents certain pubkeys from sending messages
- """
- super().__init__()
- self.nonces = {}
- self.blacklist = blacklist
- self.receiver_hotkey = receiver_hotkey
-
-
-
- def parse_signature(
- self, metadata: Dict[str, str]
- ) -> Tuple[int, str, str, str, int]:
- pass
- def check_signature(
- self,
- nonce: int,
- sender_hotkey: str,
- signature: str,
- receptor_uuid: str,
- format: int,
- ):
- pass
-
-
- def black_list_checking(self, hotkey: str, method: str):
- r"""Tries to call to blacklist function in the miner and checks if it should blacklist the pubkey"""
- pass
- def intercept_service(self, continuation, handler_call_details):
- r"""Authentication between bittensor nodes. Intercepts messages and checks them"""
-
- pass
-
\ No newline at end of file
diff --git a/commune/modules/server/grpc/proto/__init__.py b/commune/modules/server/grpc/proto/__init__.py
deleted file mode 100755
index d17806497..000000000
--- a/commune/modules/server/grpc/proto/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .server_pb2 import *
-from .server_pb2_grpc import *
\ No newline at end of file
diff --git a/commune/modules/server/grpc/proto/server.proto b/commune/modules/server/grpc/proto/server.proto
deleted file mode 100755
index f88cafdc1..000000000
--- a/commune/modules/server/grpc/proto/server.proto
+++ /dev/null
@@ -1,17 +0,0 @@
-// python3 -m grpc.tools.protoc bittensor/_proto/bittensor.proto -I. --python_out=. --grpc_python_out=.
-
-syntax = "proto3";
-
-// Service definition for tensor processing servers.
-service Server {
- // Forward tensor request.
- rpc Forward (DataBlock) returns (DataBlock) {}
-
-}
-
-
-message DataBlock {
- bytes data = 1;
- bytes metadata = 2;
- repeated DataBlock blocks = 3;
-}
diff --git a/commune/modules/server/grpc/proto/server_pb2.py b/commune/modules/server/grpc/proto/server_pb2.py
deleted file mode 100755
index 86d61960e..000000000
--- a/commune/modules/server/grpc/proto/server_pb2.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: server.proto
-"""Generated protocol buffer code."""
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='server.proto',
- package='',
- syntax='proto3',
- serialized_options=None,
- create_key=_descriptor._internal_create_key,
- serialized_pb=b'\n\x0cserver.proto\"G\n\tDataBlock\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x12\x10\n\x08metadata\x18\x02 \x01(\x0c\x12\x1a\n\x06\x62locks\x18\x03 \x03(\x0b\x32\n.DataBlock2-\n\x06Server\x12#\n\x07\x46orward\x12\n.DataBlock\x1a\n.DataBlock\"\x00\x62\x06proto3'
-)
-
-
-
-
-_DATABLOCK = _descriptor.Descriptor(
- name='DataBlock',
- full_name='DataBlock',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='DataBlock.data', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=b"",
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='metadata', full_name='DataBlock.metadata', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=b"",
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='blocks', full_name='DataBlock.blocks', index=2,
- number=3, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=16,
- serialized_end=87,
-)
-
-_DATABLOCK.fields_by_name['blocks'].message_type = _DATABLOCK
-DESCRIPTOR.message_types_by_name['DataBlock'] = _DATABLOCK
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-DataBlock = _reflection.GeneratedProtocolMessageType('DataBlock', (_message.Message,), {
- 'DESCRIPTOR' : _DATABLOCK,
- '__module__' : 'server_pb2'
- # @@protoc_insertion_point(class_scope:DataBlock)
- })
-_sym_db.RegisterMessage(DataBlock)
-
-
-
-_SERVER = _descriptor.ServiceDescriptor(
- name='Server',
- full_name='Server',
- file=DESCRIPTOR,
- index=0,
- serialized_options=None,
- create_key=_descriptor._internal_create_key,
- serialized_start=89,
- serialized_end=134,
- methods=[
- _descriptor.MethodDescriptor(
- name='Forward',
- full_name='Server.Forward',
- index=0,
- containing_service=None,
- input_type=_DATABLOCK,
- output_type=_DATABLOCK,
- serialized_options=None,
- create_key=_descriptor._internal_create_key,
- ),
-])
-_sym_db.RegisterServiceDescriptor(_SERVER)
-
-DESCRIPTOR.services_by_name['Server'] = _SERVER
-
-# @@protoc_insertion_point(module_scope)
diff --git a/commune/modules/server/grpc/proto/server_pb2_grpc.py b/commune/modules/server/grpc/proto/server_pb2_grpc.py
deleted file mode 100755
index 122613942..000000000
--- a/commune/modules/server/grpc/proto/server_pb2_grpc.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-"""Client and server classes corresponding to protobuf-defined services."""
-import grpc
-
-from . import server_pb2 as server__pb2
-
-
-class ServerStub(object):
- """Service definition for tensor processing servers.
- """
-
- def __init__(self, channel):
- """Constructor.
-
- Args:
- channel: A grpc.Channel.
- """
- self.Forward = channel.unary_unary(
- '/Server/Forward',
- request_serializer=server__pb2.DataBlock.SerializeToString,
- response_deserializer=server__pb2.DataBlock.FromString,
- )
-
-
-class ServerServicer(object):
- """Service definition for tensor processing servers.
- """
-
- def Forward(self, request, context):
- """Forward tensor request.
- """
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
-
-def add_ServerServicer_to_server(servicer, server):
- rpc_method_handlers = {
- 'Forward': grpc.unary_unary_rpc_method_handler(
- servicer.Forward,
- request_deserializer=server__pb2.DataBlock.FromString,
- response_serializer=server__pb2.DataBlock.SerializeToString,
- ),
- }
- generic_handler = grpc.method_handlers_generic_handler(
- 'Server', rpc_method_handlers)
- server.add_generic_rpc_handlers((generic_handler,))
-
-
- # This class is part of an EXPERIMENTAL API.
-class Server(object):
- """Service definition for tensor processing servers.
- """
-
- @staticmethod
- def Forward(request,
- target,
- options=(),
- channel_credentials=None,
- call_credentials=None,
- insecure=False,
- compression=None,
- wait_for_ready=None,
- timeout=None,
- metadata=None):
- return grpc.experimental.unary_unary(request, target, '/Server/Forward',
- server__pb2.DataBlock.SerializeToString,
- server__pb2.DataBlock.FromString,
- options, channel_credentials,
- insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
diff --git a/commune/modules/server/grpc/serializer.py b/commune/modules/server/grpc/serializer.py
deleted file mode 100755
index 390239fa4..000000000
--- a/commune/modules/server/grpc/serializer.py
+++ /dev/null
@@ -1,233 +0,0 @@
-""" An interface for serializing and deserializing bittensor tensors"""
-
-# I DONT GIVE A FUCK LICENSE (IDGAF)
-# Do whatever you want with this code
-# Dont pull up with your homies if it dont work.
-import numpy as np
-import torch
-import msgpack
-import msgpack_numpy
-from typing import Tuple, List, Union, Optional
-import sys
-import os
-import asyncio
-from copy import deepcopy
-from munch import Munch
-
-from commune.modules.server.grpc.proto import DataBlock
-from commune.utils.dict import dict_put, dict_get
-import commune
-import json
-
-if os.getenv('USE_STREAMLIT'):
- import streamlit as stw
-
-class Serializer(commune.Module):
- r""" Bittensor base serialization object for converting between DataBlock and their
- various python tensor equivalents. i.e. torch.Tensor or tensorflow.Tensor
- """
-
- def serialize (self, data: object, metadata:dict) -> DataBlock:
- data_type = self.get_str_type(data)
- sub_blocks = []
-
- data_type = data_type.replace('.', '_')
-
-
- if data_type in ['dict']:
- object_map = self.get_non_json_objects(x=data, object_map={})
-
- for k_index ,k in enumerate(object_map.keys()):
- v = object_map[k]
- block_ref_path = list(map(lambda x: int(x) if x.isdigit() else str(x), k.split('.')))
- k_metadata = {'block_ref_path': block_ref_path, 'block_ref_idx': k_index}
- sub_blocks.append(self.serialize(data=v, metadata=deepcopy(k_metadata)))
- dict_put(data, block_ref_path , k_metadata)
-
- serializer = getattr(self, f'serialize_{data_type}')
- data_bytes, metadata = serializer( data = data, metadata=metadata )
-
- metadata['data_type'] = data_type
- metadata_bytes = self.dict2bytes(metadata)
- return DataBlock(data=data_bytes, metadata = metadata_bytes, blocks=sub_blocks)
-
-
-
- def deserialize(self, proto: DataBlock) -> object:
- """Serializes a torch object to DataBlock wire format.
- """
- metadata = self.bytes2dict(proto.metadata)
- data_type = metadata['data_type']
- deserializer = getattr(self, f'deserialize_{data_type}')
-
-
- data = deserializer( data = proto.data , metadata= metadata)
- if len(proto.blocks) > 0:
- for proto_block in proto.blocks:
- block = self.deserialize(proto=proto_block)
- dict_put(data, block['metadata']['block_ref_path'], block['data'])
-
- output_dict = dict(data= data, metadata = metadata)
- return output_dict
-
- """
- ################ BIG DICT LAND ############################
- """
-
- def serialize_dict(self, data: dict, metadata:dict) -> DataBlock:
- data = self.dict2bytes(data=data)
- return data, metadata
-
-
- def deserialize_dict(self, data: bytes, metadata:dict) -> DataBlock:
- data = self.bytes2dict(data=data)
- return data
-
- def serialize_bytes(self, data: dict, metadata:dict) -> DataBlock:
- return data, metadata
-
- def deserialize_bytes(self, data: bytes, metadata:dict) -> DataBlock:
- return data
-
- def serialize_munch(self, data: dict, metadata:dict) -> DataBlock:
- data=self.munch2dict(data)
- data = self.dict2bytes(data=data)
- return data, metadata
-
- def deserialize_munch(self, data: bytes, metadata:dict) -> DataBlock:
- data = self.bytes2dict(data=data)
- data = self.dict2munch(data)
- return data
-
-
- def dict2bytes(self, data:dict) -> bytes:
- data_json_str = json.dumps(data)
- data_json_bytes = msgpack.packb(data_json_str)
- return data_json_bytes
-
- def bytes2dict(self, data:bytes) -> dict:
- json_object_bytes = msgpack.unpackb(data)
- return json.loads(json_object_bytes)
-
-
-
- """
- ################ BIG TORCH LAND ############################
- """
- def torch2bytes(self, data:torch.Tensor)-> bytes:
- if data.requires_grad:
- data = data.detach()
- torch_numpy = np.array(data.cpu().tolist())
- # torch_numpy = data.cpu().numpy().copy()
- data_buffer = msgpack.packb(torch_numpy, default=msgpack_numpy.encode)
- return data_buffer
-
-
- def bytes2torch(self, data:bytes, shape:list, dtype:str, requires_grad:bool=False) -> torch.Tensor:
- numpy_object = msgpack.unpackb(data, object_hook=msgpack_numpy.decode).copy()
-
- int64_workaround = bool(numpy_object.dtype == np.int64)
- if int64_workaround:
- numpy_object = numpy_object.astype(np.float64)
- torch_object = torch.tensor(numpy_object).view(shape).requires_grad_(requires_grad)
- if int64_workaround:
- dtype = torch.int64
- torch_object = torch_object.to(dtype)
- return torch_object
-
-
- def serialize_torch(self, data: torch.Tensor, metadata:dict) -> DataBlock:
-
- metadata['dtype'] = str(data.dtype)
- metadata['shape'] = list(data.shape)
- metadata['requires_grad'] = data.requires_grad
- data = self.torch2bytes(data=data)
- return data, metadata
-
- def serialize_torch_device(self, data: torch.Tensor, metadata:dict) -> DataBlock:
- metadata['dtype'] = 'torch.device'
- # convert torch device to an int
- data = data.index
- return data, metadata
- def deserrialize_torch_device(self, data: torch.Tensor, metadata:dict) -> DataBlock:
-
- return torch.device(data), metadata
-
- def deserialize_torch(self, data: bytes, metadata: dict) -> torch.Tensor:
-
- dtype = metadata['dtype']
- assert 'torch.' in dtype
-
- # if dtype == 'torch.int64':
- # dtype = 'torch.float64'
- dtype = eval(dtype)
- shape = metadata['shape']
- requires_grad = metadata['requires_grad']
- data = self.bytes2torch(data=data, shape=shape, dtype=dtype, requires_grad=requires_grad )
-
-
- return data
-
- def get_str_type(self, data):
- data_type = str(type(data)).split("'")[1]
- if data_type in ['munch.Munch', 'Munch']:
- data_type = 'munch'
- if data_type in ['torch.Tensor', 'Tensor']:
- data_type = 'torch'
-
- return data_type
-
- def get_non_json_objects(self,x:dict, object_map:dict=None, root_key:str=None, python_types:Optional[list]=[int, bool, float, tuple, dict, list, str, type(None)]):
- object_map = object_map if object_map != None else {}
- k_list = []
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
-
- for k in k_list:
- v = x[k]
- v_type = type(v)
-
- current_root_key = f'{root_key}.{k}' if root_key else k
-
- if v_type not in python_types:
- object_map[current_root_key] = v
-
- if v_type in [dict, list, tuple]:
- self.get_non_json_objects(x=v, object_map=object_map, root_key=current_root_key)
-
-
-
- return object_map
-
-
- def empty(self):
- """Returns an empty DataBlock message with the version"""
- return DataBlock()
-
- @classmethod
- def test_serialize(cls):
- module = Serializer()
- data = {'bro': {'fam': torch.ones(100,1000), 'bro': [torch.ones(1,1)]}}
- proto = module.serialize(data)
-
- @classmethod
- def test_deserialize(cls):
- module = Serializer()
- data = {'bro': {'fam':[[torch.ones(100,1000), torch.ones(100,1000)]], 'bro': [torch.ones(1,1)]}}
- proto = module.serialize(data)
- data = module.deserialize(proto)
- st.write(data)
- return True
-
- @classmethod
- def test(cls):
- for f in dir(cls):
- if f.startswith('test_'):
- getattr(cls, f)()
-
-
-if __name__ == "__main__":
- Serializer.run()
-
diff --git a/commune/modules/server/http/__init__.py b/commune/modules/server/http/__init__.py
deleted file mode 100755
index e69de29bb..000000000
diff --git a/commune/modules/server/http/client/http_client.py b/commune/modules/server/http/client/http_client.py
deleted file mode 100755
index cbb692212..000000000
--- a/commune/modules/server/http/client/http_client.py
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-from typing import Tuple, List, Union
-import sys
-import os
-import asyncio
-import requests
-from functools import partial
-import commune as c
-import aiohttp
-import json
-
-
-
-class Client(c.Module):
-
- def __init__(
- self,
- ip: str ='0.0.0.0',
- port: int = 50053 ,
- network: bool = None,
- key : str = None,
- stream:bool = False,
- loop: 'asyncio.EventLoop' = None,
- **kwargs
- ):
- self.loop = c.get_event_loop() if loop == None else loop
- self.set_client(ip =ip,port = port)
- self.serializer = c.serializer()
- self.key = c.get_key(key)
- self.my_ip = c.ip()
- self.network = c.resolve_network(network)
- self.start_timestamp = c.timestamp()
-
-
- def age(self):
- return self.start_timestamp - c.timestamp()
-
- def set_client(self,
- ip: str =None,
- port: int = None ,
- verbose: bool = False
- ):
- self.ip = ip if ip else c.default_ip
- self.port = port if port else c.free_port()
- if verbose:
- c.print(f"Connecting to {self.ip}:{self.port}", color='green')
- self.address = f"{self.ip}:{self.port}"
-
-
- def resolve_client(self, ip: str = None, port: int = None) -> None:
- if ip != None or port != None:
- self.set_client(ip =ip,port = port)
-
-
- async def async_forward(self,
- fn: str,
- args: list = None,
- kwargs: dict = None,
- ip: str = None,
- port : int= None,
- timeout: int = 10,
- stream: bool = True,
- return_error: bool = False,
- asyn: bool = True,
- full : bool = False,
- headers : dict ={'Content-Type': 'application/json'},
- **extra_kwargs):
-
- self.resolve_client(ip=ip, port=port)
-
- args = args if args else []
- kwargs = kwargs if kwargs else {}
-
- url = f"http://{self.address}/{fn}/"
-
- request_data = {
- "args": args,
- "kwargs": kwargs,
- "ip": self.my_ip,
- "timestamp": c.timestamp(),
- }
-
- # serialize this into a json string
- request_data = self.serializer.serialize( request_data)
-
- # sign the request
- request = self.key.sign(request_data, return_json=True)
-
- result = '{}'
- # start a client session and send the request
- async with aiohttp.ClientSession() as session:
- async with session.post(url, json=request, headers=headers) as response:
- if response.content_type == 'text/event-stream':
- # Process SSE events
- result = ''
- async for line in response.content:
- # remove the "data: " prefix
- event_data = line.decode('utf-8').strip()[len('data: '):]
- result += event_data
- result = json.loads(result)
- elif response.content_type == 'application/json':
- result = await asyncio.wait_for(response.json(), timeout=timeout)
- elif response.content_type == 'text/plain':
- # result = await asyncio.wait_for(response.text, timeout=timeout)
- c.print(response.text)
- result = json.loads(result)
- else:
- raise ValueError(f"Invalid response content type: {response.content_type}")
- # process output
- result = self.process_output(result)
-
- return result
-
- def process_output(self, result):
- ## handles
- assert isinstance(result, dict) and 'data' in result and 'signature' in result, f"Invalid response: {result}"
- result = self.serializer.deserialize(result['data'])['data']
- return result
-
- def forward(self,*args,return_future:bool=False, timeout:str=4, **kwargs):
- forward_future = asyncio.wait_for(self.async_forward(*args, **kwargs), timeout=timeout)
- if return_future:
- return forward_future
- else:
- return self.loop.run_until_complete(forward_future)
-
- __call__ = forward
-
- def __str__ ( self ):
- return "Client({})".format(self.address)
- def __repr__ ( self ):
- return self.__str__()
- def __exit__ ( self ):
- self.__del__()
-
-
- def test_module(self):
- module = Client(ip='0.0.0.0', port=8091)
- import torch
- data = {
- 'bro': torch.ones(10,10),
- 'fam': torch.zeros(10,10)
- }
-
- def virtual(self):
- return c.virtual_client(module = self)
-
-
diff --git a/commune/modules/server/http/client/pool/http_client_pool.py b/commune/modules/server/http/client/pool/http_client_pool.py
deleted file mode 100644
index eb1f710a9..000000000
--- a/commune/modules/server/http/client/pool/http_client_pool.py
+++ /dev/null
@@ -1,185 +0,0 @@
-""" Manages a pool of grpc connections as clients
-"""
-
-import math
-from typing import Tuple, List, Union
-from threading import Lock
-import streamlit as st
-import torch
-import asyncio
-from loguru import logger
-import concurrent
-import commune
-from concurrent.futures import ThreadPoolExecutor
-import commune
-
-class ClientPool (commune.Module):
- """ Manages a pool of grpc connections as clients
- """
- def __init__(
- self,
- modules,
- max_active_clients = 20,
-
- ):
-
- self.add_modules(modules)
- self.max_active_clients = self.max_active_clients
-
- self.client_stats = {}
- if modules == None:
- modules = self.modules()
- self.cull_mutex = Lock()
- self.total_requests = 0
-
-
- def __str__(self):
- return "ClientPool({},{})".format(len(self.clients), self.max_active_clients)
-
- def __repr__(self):
- return self.__str__()
-
- def __exit__(self):
- for client in self.clients:
- client.__del__()
-
- def forward (
- self,
- modules: List [str ] = None,
- args = None,
- kwargs = None,
- timeout: int,
- min_successes: int = None,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- r""" Forward tensor inputs to endpoints.
-
- Args:
- endpoints (:obj:`List[ bittensor.Endpoint ]` of shape :obj:`(num_endpoints)`, `required`):
- List of remote endpoints which match length of inputs. Tensors from x are sent forward to these endpoints.
-
- synapses (:obj:`List[ 'bittensor.Synapse' ]` of shape :obj:`(num_synapses)`, `required`):
- Bittensor synapse objects with arguments. Each corresponds to a synapse function on the axon.
- Responses are packed in this ordering.
-
- inputs (:obj:`List[torch.Tensor]` of shape :obj:`(num_endpoints * [shape])`, `required`):
- TODO(const): Allow multiple tensors.
- List of tensors to send to corresponsing endpoints. Tensors are of arbitrary type and shape depending on the
- modality.
-
- timeout (int):
- Request timeout.
-
- Returns:
- forward_outputs (:obj:`List[ List[ torch.FloatTensor ]]` of shape :obj:`(num_endpoints * (num_synapses * (shape)))`, `required`):
- Output encodings of tensors produced by remote endpoints. Non-responses are zeroes of common shape.
-
- forward_codes (:obj:`List[ List[bittensor.proto.ReturnCodes] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call return ops.
-
- forward_times (:obj:`List[ List [float] ]` of shape :obj:`(num_endpoints * ( num_synapses ))`, `required`):
- dendrite backward call times
- """
-
- loop = self.get_event_loop()
- return loop.run_until_complete (
- self.async_forward(kwargs=kwargs)
- )
-
-
- def add_module(self, module):
- if module in self.pool:
- return module
-
- self.pool[module] = commune.connect(module)
-
- async def async_forward (
- self,
- fn: None,
- module = None,
- args = None,
- kwargs = None,
- timeout: int = 2,
- min_successes: int = 2,
- ) -> Tuple[List[torch.Tensor], List[int], List[float]]:
- # Init clients.
-
-
-
- client = await self.async_get_clients( module )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
- # Make calls.
- running_tasks = []
- for index, (client) in enumerate(clients.items()):
- args, kwargs = self.copy(args), self.copy(kwargs)
- task = asyncio.create_task(
- client.async_forward(*args, **kwargs)
- )
- running_tasks.append(task)
-
-
- outputs = []
-
- while len(running_tasks) > 0:
-
- finished_tasks, running_tasks = await asyncio.wait( running_tasks , return_when=asyncio.FIRST_COMPLETED)
- finished_tasks, running_tasks = list(finished_tasks), list(running_tasks)
-
- responses = await asyncio.gather(*finished_tasks)
-
- for response in responses:
- if min_successes > 0:
- if response[1][0] == 1:
- outputs.append( response )
- if len(outputs) >= min_successes :
- # cancel the rest of the tasks
- [t.cancel() for t in running_tasks]
- running_tasks = [t for t in running_tasks if t.cancelled()]
- assert len(running_tasks) == 0, f'{len(running_tasks)}'
- break
- else:
-
- outputs.append( response)
-
- return outputs
-
-
-
-
- def check_clients( self ):
- r""" Destroys clients based on QPS until there are no more than max_active_clients.
- """
- with self.cull_mutex:
- # ---- Finally: Kill clients over max allowed ----
- if len(self.clients) > self.max_active_clients:
- c = list(self.clients.keys())[0]
- self.clients.pop(c, None)
-
-
-
- async def async_get_client( self,
- module = None,
- timeout=1 ) -> 'commune.Client':
- r""" Finds or creates a client TCP connection associated with the passed Neuron Endpoint
- Returns
- client: (`commune.Client`):
- client with tcp connection endpoint at endpoint.ip:endpoint.port
- """
- # ---- Find the active client for this endpoint ----
-
- modules = self.modules(module)
-
-
- if module == None:
- client = self.choice(self.clients.values())
- if module in self.clients :
- client = self.clients[module]
- else:
- client = await self.async_connect(module, timeout=timeout)
- self.clients[ client.endpoint.hotkey ] = client
-
- return client
-
diff --git a/commune/modules/server/http/client/pool/http_client_pool.yaml b/commune/modules/server/http/client/pool/http_client_pool.yaml
deleted file mode 100644
index a09e9e9c2..000000000
--- a/commune/modules/server/http/client/pool/http_client_pool.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-max_active_clients: 100
-modules: dataset
-max_staleness: 10
diff --git a/commune/modules/server/http/client/pool/pool.py b/commune/modules/server/http/client/pool/pool.py
deleted file mode 100644
index e7b4cf33a..000000000
--- a/commune/modules/server/http/client/pool/pool.py
+++ /dev/null
@@ -1,190 +0,0 @@
-""" Manages a pool of grpc connections as modules
-"""
-
-import math
-from typing import Tuple, List, Union
-from threading import Lock
-import streamlit as st
-import asyncio
-from loguru import logger
-import concurrent
-import commune
-from concurrent.futures import ThreadPoolExecutor
-import commune as c
-import asyncio
-
-class ModulePool (c.Module):
- """ Manages a pool of grpc connections as modules
- """
-
-
-
- def __init__(
- self,
- modules = None,
- max_modules:int = 20,
- stats = None,
-
- ):
- self.cull_mutex = Lock()
- self.modules = {}
- self.max_modules = max_modules
- self.add_modules(modules)
- self.set_stats(stats)
- self.total_requests = 0
-
-
- def set_stats(self, stats=None):
- if stats == None:
- stats = self.munch({})
- self.stats = stats
- return stats
- def add_module(self, *args, **kwargs)-> str:
- loop = self.get_event_loop()
- return loop.run_until_complete(self.async_add_module( *args, **kwargs))
-
- async def async_add_module(self, module:str = None, timeout=3)-> str:
- print(module)
- self.modules[module] = await c.async_connect(module, timeout=timeout,virtual=False)
- return self.modules[module]
-
-
- def add_modules(self, modules:list):
- if modules == None:
- modules = c.servers()
- if isinstance(modules, str):
- modules = c.servers(modules)
- loop = self.get_event_loop()
- return loop.run_until_complete(asyncio.gather(*[self.async_add_module(m) for m in modules]))
-
-
-
- def has_module(self, module:str)->bool:
- return bool(module in self.modules)
-
- def get_module(self, *args, **kwargs):
- loop = self.get_event_loop()
- return loop.run_until_complete(self.async_get_module(*args, **kwargs))
-
-
-
-
- async def async_get_module( self,
- module = None,
- timeout=1,
- retrials=2) -> 'c.Client':
-
- if module == None:
- module = c.choice(list(self.modules.values()))
- elif isinstance(modules, str):
- if module in self.modules :
- module = self.modules[module]
- else:
- module = await self.async_add_module(module)
- else:
- raise NotImplemented(module)
-
- return module
-
-
-
- def __str__(self):
- return "ModulePool({},{})".format(len(self.modules), self.max_modules)
-
- def __repr__(self):
- return self.__str__()
-
- # def __exit__(self):
- # for module in self.modules:
- # module.__del__()
-
- def forward (self, *args, **kwargs) :
-
- loop = self.get_event_loop()
- return loop.run_until_complete (self.async_forward(*args, **kwargs) )
-
-
- async def async_forward (
- self,
- fn:str,
- args:list = None,
- kwargs:dict = None,
- module:list = None,
- timeout: int = 2,
- ) :
- # Init modules.
-
-
-
- module = await self.async_get_module( module )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
- result = await module.async_forward(fn=fn, args=args, kwargs=kwargs, timeout=timeout)
-
-
-
- return result
-
-
- async def async_forward_pool (
- self,
- fn:str,
- args:list = None,
- kwargs:dict = None,
- modules:list = None,
- timeout: int = 2,
- min_successes: int = 2,
- ) :
- # Init modules.
-
-
-
- module = await self.async_get_module( modules )
-
-
- kwargs = {} if kwargs == None else kwargs
- args = [] if args == None else args
-
-
- outputs = []
-
- while len(running_tasks) > 0:
-
- finished_tasks, running_tasks = await asyncio.wait( running_tasks , return_when=asyncio.FIRST_COMPLETED)
- finished_tasks, running_tasks = list(finished_tasks), list(running_tasks)
-
- responses = await asyncio.gather(*finished_tasks)
-
- for response in responses:
- if min_successes > 0:
- if response[1][0] == 1:
- outputs.append( response )
- if len(outputs) >= min_successes :
- # cancel the rest of the tasks
- [t.cancel() for t in running_tasks]
- running_tasks = [t for t in running_tasks if t.cancelled()]
- assert len(running_tasks) == 0, f'{len(running_tasks)}'
- break
- else:
-
- outputs.append( response)
-
- return outputs
-
- @classmethod
- def test(cls, **kwargs):
- self = cls(modules='module')
- t = c.time()
- for i in range(10):
- print(i)
- output = self.forward('namespace')
- cls.print(output)
-
- cls.print('time', c.time() - t)
-
-
-if __name__ == '__main__':
- ModulePool.run()
\ No newline at end of file
diff --git a/commune/modules/server/http/serializer.py b/commune/modules/server/http/serializer.py
deleted file mode 100644
index 6960b4b57..000000000
--- a/commune/modules/server/http/serializer.py
+++ /dev/null
@@ -1,269 +0,0 @@
-""" An interface for serializing and deserializing bittensor tensors"""
-
-# I DONT GIVE A FUCK LICENSE (IDGAF)
-# Do whatever you want with this code
-# Dont pull up with your homies if it dont work.
-import numpy as np
-import msgpack
-import msgpack_numpy
-from typing import Tuple, List, Union, Optional
-import sys
-import os
-import asyncio
-from copy import deepcopy
-from munch import Munch
-
-import commune as c
-import json
-import torch
-
-
-class Serializer(c.Module):
- r""" Bittensor base serialization object for converting between DataBlock and their
- various python tensor equivalents. i.e. torch.Tensor or tensorflow.Tensor
- """
- @staticmethod
- def resolve_key_list(x):
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
- elif type(x) in [tuple, set]:
- # convert to list, to format as json
- x = list(x)
- k_list = list(range(len(x)))
- else:
- raise Exception(f'{type(x)} not supported to get the keylist fam')
-
- python_types = [int, bool, float, tuple, dict, list, str, type(None)]
- def serialize(self,x:dict, mode = 'str'):
- x = c.copy(x)
- k_list = []
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
- elif type(x) in [tuple, set]:
- # convert to list, to format as json
- x = list(x)
- k_list = list(range(len(x)))
-
- for k in k_list:
- v = x[k]
- v_type = type(v)
- if v_type in [dict, list, tuple, set]:
- x[k] = self.serialize(x=v, mode=None)
- else:
- str_v_type = self.get_str_type(data=v)
- if hasattr(self, f'serialize_{str_v_type}'):
- v = getattr(self, f'serialize_{str_v_type}')(data=v)
- x[k] = {'data': v, 'data_type': str_v_type, 'serialized': True}
-
- if mode == 'str':
- x = self.dict2str(x)
- elif mode == 'bytes':
- x = self.dict2bytes(x)
- elif mode == None:
- pass
- else:
- raise Exception(f'{mode} not supported')
-
- return x
-
-
-
- def is_serialized(self, data):
- if isinstance(data, dict) and \
- data.get('serialized', False) == True and \
- 'data' in data and 'data_type' in data:
- return True
- else:
- return False
-
- def deserialize(self, x) -> object:
- """Serializes a torch object to DataBlock wire format.
- """
- if isinstance(x, str):
- x = self.str2dict(x)
- k_list = []
- if isinstance(x, dict):
- k_list = list(x.keys())
- elif isinstance(x, list):
- k_list = list(range(len(x)))
- elif type(x) in [tuple, set]:
- # convert to list, to format as json
- x = list(x)
- k_list = list(range(len(x)))
-
- for k in k_list:
- v = x[k]
- if type(v) in [dict, list, tuple, set]:
- x[k] = self.deserialize(x=v)
- if self.is_serialized(v):
- data_type = v['data_type']
- data = v['data']
- if hasattr(self, f'deserialize_{data_type}'):
- x[k] = getattr(self, f'deserialize_{data_type}')(data=data)
-
- return x
-
- """
- ################ BIG DICT LAND ############################
- """
-
- def serialize_dict(self, data: dict) -> str :
- data = self.dict2bytes(data=data)
- return data
-
- def deserialize_dict(self, data: bytes) -> dict:
- data = self.bytes2dict(data=data)
- return data
-
- def serialize_bytes(self, data: dict) -> bytes:
- data = data
-
- def deserialize_bytes(self, data: bytes) -> 'DataBlock':
- if isinstance(data, str):
- data = self.str2bytes(data)
- return data
-
- def serialize_munch(self, data: dict) -> str:
- data=self.munch2dict(data)
- data = self.dict2str(data=data)
- return data
-
- def deserialize_munch(self, data: bytes) -> 'Munch':
-
- data = self.bytes2dict(data=data)
- data = self.dict2munch(data)
- return data
-
- def dict2bytes(self, data:dict) -> bytes:
- data_json_str = json.dumps(data)
- data_json_bytes = msgpack.packb(data_json_str)
- return data_json_bytes
- def dict2str(self, data:dict) -> bytes:
- data_json_str = json.dumps(data)
- return data_json_str
- def str2dict(self, data:str) -> bytes:
- data_json_str = json.loads(data)
- return data_json_str
-
- @classmethod
- def hex2str(cls, x, **kwargs):
- return x.hex()
-
- bytes2str = hex2str
-
- @classmethod
- def str2hex(cls, x, **kwargs):
- return bytes.fromhex(x)
-
- str2bytes = str2hex
-
-
-
- def bytes2dict(self, data:bytes) -> dict:
- json_object_bytes = msgpack.unpackb(data)
- return json.loads(json_object_bytes)
-
- """
- ################ BIG TORCH LAND ############################
- """
- def torch2bytes(self, data:torch.Tensor)-> bytes:
- return self.numpy2bytes(self.torch2numpy(data))
-
- def torch2numpy(self, data:torch.Tensor)-> np.ndarray:
- if data.requires_grad:
- data = data.detach()
- data = data.cpu().numpy()
- return data
-
-
- def numpy2bytes(self, data:np.ndarray)-> bytes:
- output = msgpack.packb(data, default=msgpack_numpy.encode)
- return output
-
- def bytes2torch(self, data:bytes, ) -> torch.Tensor:
- numpy_object = self.bytes2numpy(data)
-
- int64_workaround = bool(numpy_object.dtype == np.int64)
- if int64_workaround:
- numpy_object = numpy_object.astype(np.float64)
- torch_object = torch.tensor(numpy_object)
- if int64_workaround:
- dtype = torch.int64
- return torch_object
-
- def bytes2numpy(self, data:bytes) -> np.ndarray:
- output = msgpack.unpackb(data, object_hook=msgpack_numpy.decode)
- return output
-
-
-
-
- def serialize_torch(self, data: torch.Tensor) -> 'DataBlock':
- from safetensors.torch import save
- output = save({'data':data})
- return self.bytes2str(output)
-
-
-
-
- def deserialize_torch(self, data: dict) -> torch.Tensor:
- from safetensors.torch import load
- if isinstance(data, str):
- data = self.str2bytes(data)
- data = load(data)
- return data['data']
-
- def get_str_type(self, data):
- data_type = str(type(data)).split("'")[1]
- if data_type in ['munch.Munch', 'Munch']:
- data_type = 'munch'
- if data_type in ['torch.Tensor', 'Tensor']:
- data_type = 'torch'
-
- return data_type
-
- @classmethod
- def test_serialize(cls):
- module = Serializer()
- data = {'bro': {'fam': torch.ones(2,2), 'bro': [torch.ones(1,1)]}}
- proto = module.serialize(data)
- module.deserialize(proto)
-
- @classmethod
- def test_deserialize(cls):
- module = Serializer()
-
- t = c.time()
- data = {'bro': {'fam':[[torch.randn(100,1000), torch.randn(100,1000)]], 'bro': [torch.ones(1,1)]}}
- proto = module.serialize(data)
- data = module.deserialize(proto)
- c.print(t - c.time())
-
- # return True
-
- @classmethod
- def test(cls, size=1):
- self = cls()
- stats = {}
- data = {'bro': {'fam': torch.randn(size,size), 'bro': [torch.ones(1,1)]}}
-
- t = c.time()
- serialized_data = self.serialize(data)
- assert isinstance(serialized_data, str), f"serialized_data must be a str, not {type(serialized_data)}"
- deserialized_data = self.deserialize(serialized_data)
-
- assert deserialized_data['bro']['fam'].shape == data['bro']['fam'].shape
- assert deserialized_data['bro']['bro'][0].shape == data['bro']['bro'][0].shape
-
- stats['elapsed_time'] = c.time() - t
- stats['size_bytes'] = c.sizeof(data)
- stats['size_bytes_compressed'] = c.sizeof(serialized_data)
- stats['size_deserialized_data'] = c.sizeof(deserialized_data)
- stats['compression_ratio'] = stats['size_bytes'] / stats['size_bytes_compressed']
- stats['mb_per_second'] = c.round((stats['size_bytes'] / stats['elapsed_time']) / 1e6, 3)
- c.print(stats)
-
diff --git a/commune/modules/server/http/server_http.py b/commune/modules/server/http/server_http.py
deleted file mode 100755
index 15ea1dda0..000000000
--- a/commune/modules/server/http/server_http.py
+++ /dev/null
@@ -1,201 +0,0 @@
-
-from typing import Dict, List, Optional, Union
-import commune as c
-import torch
-import traceback
-import json
-
-
-
-
-class ServerHTTP(c.Module):
- def __init__(
- self,
- module: Union[c.Module, object],
- name: str = None,
- network:str = 'local',
- port: Optional[int] = None,
- sse: bool = True,
- chunk_size: int = 42_000,
- max_request_staleness: int = 60) -> 'Server':
-
- self.sse = sse
- self.serializer = c.module('serializer')()
- self.ip = c.default_ip # default to '0.0.0.0'
- self.port = c.resolve_port(port)
- self.address = f"{self.ip}:{self.port}"
- self.max_request_staleness = max_request_staleness
- self.chunk_size = chunk_size
- self.network = network
-
- if name == None:
- if hasattr(module, 'server_name'):
- name = module.server_name
- else:
- name = module.__class__.__name__
-
-
- self.module = module
- c.print(self.module, type(self.module), module.key)
- self.key = module.key
- # register the server
- self.name = name
- module.ip = self.ip
- module.port = self.port
- module.address = self.address
- self.set_api(ip=self.ip, port=self.port)
-
- def set_api(self, ip = None, port = None):
- ip = self.ip if ip == None else ip
- port = self.port if port == None else port
- from fastapi import FastAPI
- from fastapi.middleware.cors import CORSMiddleware
-
- self.app = FastAPI()
- self.app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"],
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
-
-
- @self.app.post("/{fn}")
- async def forward_api(fn:str, input:dict):
- try:
-
- input['fn'] = fn
-
- input = self.process_input(input)
-
- data = input['data']
- args = data.get('args',[])
- kwargs = data.get('kwargs', {})
-
- result = self.forward(fn=fn,args=args, kwargs=kwargs)
- success = True
-
- except Exception as e:
- result = c.detailed_error(e)
- success = False
-
- result = self.process_result(result)
-
- if success:
- c.print(f'✅ Success: {self.name}::{fn} --> {input["address"][:5]}... ✅\033 ')
- else:
- c.print(f'🚨 Error: {self.name}::{fn} --> {input["address"][:5]}... 🚨\033')
- c.print(result)
-
- return result
-
- self.serve()
-
-
-
- def state_dict(self) -> Dict:
- return {
- 'ip': self.ip,
- 'port': self.port,
- 'address': self.address,
- }
-
-
- def test(self):
- r"""Test the HTTP server.
- """
- # Test the server here if needed
- c.print(self.state_dict(), color='green')
- return self
-
-
- def process_input(self,input: dict) -> bool:
- assert 'data' in input, f"Data not included"
- assert 'signature' in input, f"Data not signed"
- # you can verify the input with the server key class
- assert self.key.verify(input), f"Data not signed with correct key"
- # deserialize the data
- input['data'] = self.serializer.deserialize(input['data'])
- # here we want to verify the data is signed with the correct key
- request_staleness = c.timestamp() - input['data'].get('timestamp', 0)
-
- # verifty the request is not too old
- assert request_staleness < self.max_request_staleness, f"Request is too old, {request_staleness} > MAX_STALENESS ({self.max_request_staleness}) seconds old"
-
- # verify the input with the access module
- input = self.module.access_module.verify(input)
-
- return input
-
-
- def process_result(self, result):
- if self.sse:
- # for sse we want to wrap the generator in an eventsource response
- from sse_starlette.sse import EventSourceResponse
- result = self.generator_wrapper(result)
- return EventSourceResponse(result)
- else:
- # if we are not
- if c.is_generator(result):
- result = list(result)
- result = self.serializer.serialize({'data': result})
- result = self.key.sign(result, return_json=True)
- return result
-
-
- def generator_wrapper(self, generator):
- if not c.is_generator(generator):
- generator = [generator]
-
- for item in generator:
- # we wrap the item in a json object, just like the serializer does
- item = self.serializer.serialize({'data': item})
- item = self.key.sign(item, return_json=True)
- item = json.dumps(item)
-
-
- # # get size of chunk
- # item_size = len(item)
- # if item_size > chunk_size:
- # # if the item is too big, we need to chunk it
- # item_hash = c.hash(item)
- # chunks =[f'CHUNKSTART:{item_hash}'] + [item[i:i+chunk_size] for i in range(0, item_size, chunk_size)] + [f'CHUNKEND:{item_hash}']
- # # we need to yield the chunks in a format that the eventsource response can understand
- # for chunk in chunks:
- # yield chunk
- # else:
- yield item
-
-
- def serve(self, **kwargs):
- import uvicorn
-
- try:
- c.print(f'\033🚀 Serving {self.name} on {self.address} 🚀\033')
- c.register_server(name=self.name, address = self.address, network=self.network)
- c.print(f'\033🚀 Registered {self.name} on {self.ip}:{self.port} 🚀\033')
- uvicorn.run(self.app, host=c.default_ip, port=self.port)
- except Exception as e:
- c.print(e, color='red')
- c.deregister_server(self.name, network=self.network)
- finally:
- c.deregister_server(self.name, network=self.network)
-
-
- def forward(self, fn: str, args: List = None, kwargs: Dict = None, **extra_kwargs):
- if args is None:
- args = []
- if kwargs is None:
- kwargs = {}
- obj = getattr(self.module, fn)
- if callable(obj):
- response = obj(*args, **kwargs)
- else:
- response = obj
- return response
-
-
- def __del__(self):
- c.deregister_server(self.name)
-
diff --git a/commune/modules/server/server.py b/commune/modules/server/server.py
deleted file mode 100644
index 4ce5f742f..000000000
--- a/commune/modules/server/server.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import commune as c
-
-class Server(c.Module):
-
- @classmethod
- def test(cls) -> dict:
- servers = c.servers()
- c.print(servers)
- tag = 'test'
- module_name = c.serve(module='module', tag=tag)
- c.wait_for_server(module_name)
- assert module_name in c.servers()
-
- c.kill(module_name)
- assert module_name not in c.servers()
- return {'success': True, 'msg': 'server test passed'}
\ No newline at end of file
diff --git a/commune/modules/server/ws/client_ws.py b/commune/modules/server/ws/client_ws.py
deleted file mode 100644
index 3650e82e4..000000000
--- a/commune/modules/server/ws/client_ws.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import asyncio
-import websockets
-import commune as c
-
-class WSClient(c.Module):
-
-
- def __init__(self,
- name ,
- start:bool = True,
- network: dict = None,
- ):
- if ':' in ip:
- ip, port = ip.split(':')
-
- namespace = c.namespace(network=network)
- self.address = namespace.get(name, None)
-
-
- def resolve_address(cls, address=None):
- if address == None:
- address = self.address
- if not 'ws://' in address:
- address = f'ws://{address}'
- assert isinstance(address, str), f'address must be a string, not {type(address)}'
- return address
-
- async def async_forward(self, data='hello', address = None):
-
- address = self.resolve_address(address=address)
-
-
-
-
- async with websockets.connect(address) as websocket:
- await websocket.send(data)
- response = await websocket.recv()
-
- return response
-
- def forward(self, data='hello', address = None):
- return asyncio.get_event_loop().run_until_complete(self.async_forward(data=data, address=address))
-
- @staticmethod
- async def recv(address):
- chunks = []
- async with websockets.connect(address) as websocket:
- chunk = await websocket.recv(address)
- chunks.append(chunk)
diff --git a/commune/modules/server/ws/filetransfer.py b/commune/modules/server/ws/filetransfer.py
deleted file mode 100644
index ab2b68634..000000000
--- a/commune/modules/server/ws/filetransfer.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import asyncio
-import websockets
-import commune as c
-
-class FileTransfer(c.Module):
-
-
- def __init__(self,
- port:int=None,
- buffer_size:int=-1
- )
-
- self.set_server(port=port)
- self.set_queue(buffer_size=buffer_size)
-
- @staticmethod
- async def send_file(filename, address):
- async with websockets.connect(address) as websocket:
- with open(filename, 'rb') as file:
- while True:
- chunk = file.read(1024)
- if not chunk:
- break
- await websocket.send(chunk)
- await websocket.send('END')
-
- @staticmethod
- async def receive_file(address):
- async with websockets.connect(address) as websocket:
- with open('received_file.txt', 'wb') as file:
- while True:
- chunk = await websocket.recv()
- if chunk == 'END':
- break
- file.write(chunk)
-
- async def forward(websocket, path='file_to_send.txt'):
- with open(path, 'rb') as file:
- while True:
- chunk = file.read(1024)
- if not chunk:
- break
- await websocket.send(chunk)
- await websocket.send('END')
-
- def set_queue(self, buffer_size:int):
- import queue
- self.queue = queue.Queue(buffer_size)
-
-
- def set_server(self,port):
- port = self.resolve_port(port)
- start_server = websockets.serve(self.forward, 'localhost', port)
- asyncio.get_event_loop().run_until_complete(start_server)
- asyncio.get_event_loop().run_forever()
-
-
-
-if __name__ == "__main__":
- FileTransfer.run()
diff --git a/commune/modules/server/ws/server.py b/commune/modules/server/ws/server.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/commune/modules/server/ws/server_ws.py b/commune/modules/server/ws/server_ws.py
deleted file mode 100644
index 8dd8220b1..000000000
--- a/commune/modules/server/ws/server_ws.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import asyncio
-import websockets
-import commune as c
-
-class WS(c.Module):
-
-
- def __init__(self,
- ip = '0.0.0.0',
- port:int=None,
- queue_size:int=-1,
- verbose:bool = True):
- self.set_server(ip=ip, port=port, queue_size=queue_size, verbose=verbose)
-
- @staticmethod
- def start(**kwargs):
- WS(**kwargs)
-
- def set_server(self, ip = '0.0.0.0', port = None, queue_size = -1, verbose = False):
- self.ip = c.resolve_ip(ip)
- self.port = c.resolve_port(port)
- self.queue = c.queue(queue_size)
- self.address = f'ws://{self.ip}:{self.port}'
- self.server = websockets.serve(self.forward, self.ip, self.port)
- c.print(f'Starting Server on {self.ip}:{self.port}')
- asyncio.get_event_loop().run_until_complete(self.server)
- asyncio.get_event_loop().run_forever()
-
-
- def put(self, chunk):
- return self.queue.put(chunk)
-
- async def forward(self, websocket):
- c.print(f'Starting Server Forwarding from {self.ip}:{self.port}')
-
- while True:
- try:
- c.print('waiting for data')
- data = await websocket.recv()
- c.print(f'chunk -> {data}')
- await websocket.send(data)
- c.print(f'sent -> {data}')
- except Exception as e:
- c.print(f'An error occurred: {e}')
-
- @classmethod
- def test(cls):
- c.print('Starting test')
- cls.remote_fn(fn='start', kwargs={})
- c.print('Finished test')
-
-
diff --git a/commune/modules/ssh/ssh.py b/commune/modules/ssh/ssh.py
deleted file mode 100644
index 82cbfc691..000000000
--- a/commune/modules/ssh/ssh.py
+++ /dev/null
@@ -1,183 +0,0 @@
-import commune as c
-
-class SSH(c.Module):
- host_data_path = f'{c.datapath}/ssh.json'
- @classmethod
- def call(cls,
- *cmd_args, host = None, cwd=None, verbose=False, **kwargs ):
- """s
- Run a command on a remote server using SSH.
-
- :param host: Hostname or IP address of the remote machine.
- :param port: SSH port (typically 22).
- :param username: SSH username.
- :param password: SSH password.
- :param command: Command to be executed on the remote machine.
- :return: Command output.
- """
- command = ' '.join(cmd_args)
-
- if cwd != None:
- command = f'cd {cwd} ; {command}'
-
-
- import paramiko
- hosts = cls.hosts()
- if host == None:
- host = list(hosts.keys())[0]
- if host not in hosts:
- raise Exception(f'Host {host} not found')
- host = hosts[host]
-
- # Create an SSH client instance.
- client = paramiko.SSHClient()
-
- # Automatically add the server's host key (this is insecure and used for demonstration;
- # in production, you should have the remote server's public key in known_hosts)
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- # Connect to the remote server
- client.connect(host['host'],
- port=host['port'],
- username=host['user'],
- password=host['pwd'])
-
- # Execute command
- stdin, stdout, stderr = client.exec_command(command)
-
- output = []
- for line in stdout.readlines():
- output += [line.strip()]
- if verbose:
- text = f'[green]{host}[/green] | {line.strip()}'
- c.print(text, color='green')
-
-
- error = []
- for line in stderr.readlines():
- error += [line.strip()]
- if verbose:
- text = f'[red]{host}[/red] | {line.strip()}'
- c.print(text, color='red')
-
- # Return the result
- error = '\n'.join(error)
- output = '\n'.join(output)
-
- if len(error) > 0:
- output = {'error': error, 'output': output}
-
- stdin.close()
- stdout.close()
- stderr.close()
- # Close the SSH connection
- client.close()
-
- return output
-
- def serve(self, **kwargs):
- return self.call(**kwargs)
-
- @classmethod
- def add_host(cls,
- host:str = '0.0.0.0',
- port:int = 22,
- user:str = 'root',
- pwd:str = None,
- name : str = None
- ):
-
- hosts = cls.hosts()
- host = {
- 'host': host,
- 'port': port,
- 'user': user,
- 'pwd': pwd
- }
- if name == None:
- cnt = 0
- name = f'{user}{cnt}'
-
- while name in hosts:
- name = f'{user}{cnt}'
- cnt += 1
-
- hosts[name] = host
- cls.save_hosts(hosts)
-
- return {'status': 'success', '': f'Host added', }
-
- @classmethod
- def save_hosts(cls, hosts):
- cls.put_json(cls.host_data_path, hosts)
- @classmethod
- def load_hosts(cls):
- return cls.get_json(cls.host_data_path, {})
-
- @classmethod
- def switch_hosts(cls, path):
- hosts = c.get_json(path)
- cls.save_hosts(hosts)
- return {'status': 'success', 'msg': f'Host data path switched to {path}'}
-
- @classmethod
- def rm_host(cls, name):
- hosts = cls.hosts()
- if name in hosts:
- del hosts[name]
- cls.put_json(cls.host_data_path, hosts)
- return {'status': 'success', 'msg': f'Host {name} removed'}
- else:
- return {'status': 'error', 'msg': f'Host {name} not found'}
-
- @classmethod
- def hosts(cls, search=None):
- hosts = cls.get_json(cls.host_data_path, {})
- if search != None:
- hosts = {k:v for k,v in hosts.items() if search in k}
- return hosts
-
- @classmethod
- def host(self, name):
- hosts = self.hosts()
-
- if name not in hosts:
- raise Exception(f'Host {name} not found')
-
- return hosts[name]
-
-
- @classmethod
- def host_exists(self, name):
- return name in self.hosts()
-
- @classmethod
- def install(self):
- c.cmd('pip3 install paramiko')
-
-
- def test(self):
- # Test SSH
- c.print(self.call('ls'))
-
- @classmethod
- def pool(cls, *commands, search=None, cwd=None, timeout=100, **kwargs):
- hosts = cls.hosts(search=search)
- results = {}
- for host in hosts:
- result_future = c.submit(cls.call, args=commands, kwargs=dict(host=host, cwd=cwd, **kwargs), return_future=True)
- results[host] = result_future
-
- result_values = c.wait(list(results.values()), timeout=timeout)
- results = dict(zip(results.keys(), result_values))
- results = {k:v for k,v in results.items()}
- for k,v in results.items():
- if isinstance(v, str):
- results[k] = v.split('\n')
- if len(results[k])>0 and len(results[k][-1]) == 0:
- results[k] = results[k][:-1]
-
-
-
- return results
-
diff --git a/commune/modules/storage/storage.py b/commune/modules/storage/storage.py
deleted file mode 100644
index 789c1335f..000000000
--- a/commune/modules/storage/storage.py
+++ /dev/null
@@ -1,197 +0,0 @@
-import commune as c
-from typing import *
-import streamlit as st
-
-class Storage(c.Module):
- whitelist: List = ['put', 'get', 'get_hash']
-
- def __init__(self, max_replicas:int = 1, network='local',**kwargs):
- self.replica_map = {}
- self.max_replicas = max_replicas
- self.network = network
- self.set_config(kwargs=locals())
- self.serializer = c.module('serializer')()
- self.executor = c.module('executor')()
-
-
-
- @property
- def store_dirpath(self) -> str:
- tag = self.tag
- if tag == None:
- tag = 'base'
- return self.resolve_path(f'{tag}.store')
-
- def resolve_store_path(self, key: str) -> str:
- path = f'{self.store_dirpath}/{key}'
- return path
-
- def resolve_key(self, key=None) -> str:
- if key == None:
- key = self.key
- if isinstance(key, str):
- key = c.get_key(key)
- return key
-
- def put(self, k, v: Dict, encrypt:bool=False, replicas = 1, key=None):
- timestamp = c.timestamp()
- obj = v
-
- k = self.resolve_store_path(k)
- # serialize
- v = self.serializer.serialize(obj)
- if encrypt:
- v = self.key.encrypt(v)
- v = self.key.sign(v, return_json=True)
- v['encrypted'] = encrypt
- v['timestamp'] = timestamp
-
- if replicas > 1:
- self.replicate(k, v, replicas=replicas)
- self.put_json(k, v)
- size_bytes = self.sizeof(v)
- return {'success': True, 'key': k, 'size_bytes': size_bytes, 'replica_map': self.replica_map}
-
- def replicate(self, k, v, replicas=2):
- replica_map = self.get('replica_map', default={})
- peer = self.random_peer()
- peer.put(k, v)
- replica_map[k] = [peer]
-
-
-
-
- def check_replicas(self):
-
- replicas = self.replicas
- c.print(replicas)
- c.print(replicas)
-
-
- def get(self,k, deserialize:bool= True, key=None) -> Any:
- k = self.resolve_store_path(k)
- v = self.get_json(k, {})
-
- if 'data' not in v:
- return {'success': False, 'error': 'No data found'}
- c.print(v)
- if 'encrypted' in v and v['encrypted']:
- c.print(v)
- v['data'] = self.key.decrypt(v['data'])
-
-
- if deserialize:
- v['data'] = self.serializer.deserialize(v['data'])
- return v['data']
-
-
- def replicate(self, k, module) -> str:
- self.replicas
-
- def get_hash(self, k: str, seed : int= None , seed_sep:str = '') -> str:
- obj = self.get(k, deserialize=False)
- c.print(obj)
- if seed != None:
- obj = str(obj) + seed_sep + str(seed)
- return self.hash(obj, seed=seed)
-
- def resolve_seed(self, seed: int = None) -> int:
- return c.timestamp() if seed == None else seed
-
- def remote_has(self, k: str, module: str, seed=None, **kwargs) -> bool:
- if isinstance(module, str):
- module = c.connect(module, **kwargs)
- seed = self.resolve_seed(seed)
- obj = self.get(k)
- obj['seed'] = seed
- local_hash = c.hash(obj)
- remote_hash = module.get_hash(k, seed=seed)
- return bool(local_hash == remote_hash)
-
- def exists(self, k) -> bool:
- path = self.resolve_store_path(k)
- return c.exists(path)
- has = exists
-
- def rm(self, k) -> bool:
- assert self.exists(k), f'Key {k} does not exist'
- path = self.resolve_store_path(k)
- return c.rm(path)
-
- def items(self, search=None) -> List:
- path = self.store_dirpath
- path += f'/{search}' if search != None else ''
- return c.ls(path)
-
- def refresh(self) -> None:
- path = self.store_dirpath
- return c.rm(path)
-
- @property
- def key2address(self) -> Dict:
- key2address = {}
- for k, v in self.store.items():
- id = v['ss58_address']
- if id in key2address:
- key2address[v['ss58_address']] += [k]
- else:
- key2address[v['ss58_address']] = [k]
- return key2address
-
- @classmethod
- def cachefn(cls, func, max_age=60, update=False, cache=True, cache_folder='cachefn'):
- import functools
- path_name = cache_folder+'/'+func.__name__
- def wrapper(*args, **kwargs):
- fn_name = func.__name__
- cache_params = {'max_age': max_age, 'cache': cache}
- for k, v in cache_params.items():
- cache_params[k] = kwargs.pop(k, v)
- if not update:
- result = cls.get(fn_name, default=None, **cache_params)
- if result != None:
- return result
-
- result = func(*args, **kwargs)
-
- if cache:
- cls.put(fn_name, result, cache=cache)
-
- return result
-
- return wrapper
-
- @classmethod
- def test(cls):
- c.print('STARTING')
- self = cls()
- import torch
- object_list = [0, {'fam': 1}, 'whadup', {'tensor': torch.rand(3,3)}, {'tensor': torch.rand(3,3), 'fam': 1}]
-
- for encrypt in [True, False]:
- for obj in object_list:
- c.print(f'putting {obj}')
- self.put('test', obj,encrypt=encrypt)
- get_obj = self.get('test', deserialize=False)
- obj_str = self.serializer.serialize(obj)
-
- # test hash
- assert self.get_hash('test', seed=1) == self.get_hash('test', seed=1)
- assert self.get_hash('test', seed=1) != self.get_hash('test', seed=2)
- assert obj_str == obj_str, f'Failed to put {obj} and get {get_obj}'
-
- self.rm('test')
-
- @classmethod
- def test_verify(cls):
- storage_modules = [cls() for i in range(10)]
- object_list = [0, {'fam': 1}, 'whadup', {'tensor': torch.rand(3,3)}, {'tensor': torch.rand(3,3), 'fam': 1}]
- for i, x in enumerate(object_list):
- for i, storage in enumerate(storage_modules):
- storage.put('test', x)
- seed = c.time()
- for i, storage_i in enumerate(storage_modules):
- for j, storage_j in enumerate(storage_modules):
- c.print(f'Verifying i={i} j={j}')
- assert storage_i.get_hash('test', seed=seed) == storage_j.get_hash('test', seed=seed)
-
diff --git a/commune/modules/storage/vali/storage_vali.py b/commune/modules/storage/vali/storage_vali.py
deleted file mode 100644
index 3359f50a5..000000000
--- a/commune/modules/storage/vali/storage_vali.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import commune as c
-from typing import *
-
-
-class StorageVali(c.Module):
- def __init__(self, config=None, **kwargs):
- config = self.set_config(config, kwargs=kwargs)
- history = {}
-
- self.storage = c.module('storage')()
-
- storage_peers = {}
-
- def get_storage_peer_info(self, name:str) -> Dict:
- default_storage_peer = {'address': None, 'size': 0, 'stored_keys': [], 'w': 0}
- return self.get(f'{self.tag}/peers/{name}', default_storage_peer)
-
-
-
- def set_storage_peer_info(self, name:str, value:dict):
- assert isinstance(value, dict)
- assert 'address' in value
- assert 'size' in value
- assert 'stored_keys' in value
- assert 'w' in value
-
- return self.put(f'{self.tag}/peers/{name}', value)
-
- def score_module(self, module, **kwargs) -> float:
-
-
-
- info = module.info()
- key = self.storage.next_key()
-
- obj = self.storage.get(key, deserialize=False)
-
- obj_size = c.sizeof(obj)
- remote_obj_key = c.hash(obj)
- remote_has = self.storage.remote_has(remote_obj_key, module=module)
- if not remote_has:
- module.put(key, obj)
-
- storage_peer = self.get_storage_peer(info['name'])
-
- # does the module have the key
- remote_has = self.storage.remote_has(remote_obj_key, module=module)
-
-
- # if the module has the key, then add it to the storage_peer
- if remote_has:
- if key not in storage_peer['stored_keys']:
- storage_peer['stored_keys'] += [key]
- storage_peer['size'] += obj_size
- else:
- module.put(remote_obj_key, obj, timeout=self.config.storage_timeout)
- remote_has = self.storage.remote_has(remote_obj_key, module=module)
- if remote_has:
- if key not in storage_peer['stored_keys']:
- storage_peer['stored_keys'] += [key]
- storage_peer['size'] += obj_size
- else:
-
- storage_peer['size'] -= obj_size
- storage_peer['stored_keys'] = [k for k in storage_peer['stored_keys'] if k != key]
-
- # ensure no duplicates
- storage_peer['stored_keys'] = list(set(storage_peer['stored_keys']))
- storage_peer['size'] = max(storage_peer['size'], 0)
-
- # set weight
- storage_peer['w'] = storage_peer['size']
- self.set_storage_peer(info['name'], storage_peer)
-
- return storage_peer
-
-
-
- def put(self, *args,**kwargs):
- return self.storage.put(*args,**kwargs)
-
-
- def get(self, *args,**kwargs):
- return self.storage.get(*args,**kwargs)
-
-
- @classmethod
- def test(cls, n=10):
- storage = [c.module('storage')() for i in range(n)]
- self = cls()
-
- self.score_module(storage[0])
-
diff --git a/commune/modules/storage/vali/storage_vali.yaml b/commune/modules/storage/vali/storage_vali.yaml
deleted file mode 100644
index 6d44951ac..000000000
--- a/commune/modules/storage/vali/storage_vali.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-netuid: 0
-module_prefix: storage
-storage_timeout: 5
-tag: base
-
diff --git a/commune/modules/streamlit/__init__.py b/commune/modules/streamlit/__init__.py
deleted file mode 100755
index d0e9d9eb7..000000000
--- a/commune/modules/streamlit/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .streamlit_module import StreamlitModule
-from .utils import *
\ No newline at end of file
diff --git a/commune/modules/streamlit/streamlit_module.py b/commune/modules/streamlit/streamlit_module.py
deleted file mode 100755
index cf24210b0..000000000
--- a/commune/modules/streamlit/streamlit_module.py
+++ /dev/null
@@ -1,497 +0,0 @@
-
-
-import os
-import sys
-import streamlit as st
-import plotly.graph_objects as go
-import pandas as pd
-import plotly.express as px
-# from commune.plot.dag import DagModule
-
-import commune as c
-
-
-
-class StreamlitModule(c.Module):
-
- height:int=1000
- width:int=1000
- theme: str= 'plotly_dark'
-
- @property
- def streamlit_functions(self):
- return [fn for fn in dir(self) if fn.startswith('st_')]
-
- def run(self, data, plots=[], default_plot ='histogram', title=None ):
-
- self.cols= st.columns([1,3])
- if len(plots) == 0:
- plots = self.plot_options()
-
- if default_plot not in plots:
- default_plot = plots[0]
- supported_types = [pd.DataFrame]
- if isinstance(data, pd.DataFrame):
- df = data
- with self.cols[1]:
- if len(plots) > 1:
- name2index = {_name:_idx for _idx, _name in enumerate(plots)}
- plot = st.selectbox('Choose a Plot', plots, name2index[default_plot])
- else:
- plot = plots[0]
- form = st.form(F'Params for {plot}')
- with form:
- fig = getattr(self, 'st_plot_'+ plot)(df)
- form.form_submit_button("Render")
-
- else:
- raise NotImplementedError(f'Broooooo, hold on, you can only use the following {supported_types}')
- fig.update_layout(height=800)
- self.show(fig)
-
- @staticmethod
- def metrics_dict(x, num_rows:int = 1):
- num_elements = len(x)
- num_cols = num_elements//num_rows
- row_cols = [st.columns(num_cols) for i in range(num_rows)]
- for i in range(num_elements):
- k = list(x.keys())[i]
- v = list(x.values())[i]
- row_idx = i//num_cols
- col_idx = i%num_cols
- row_cols[row_idx][col_idx].metric(k, int(v))
-
- def plot_options(self, prefix:str ='st_plot'):
- plot_options = self.fns(prefix)
- return [p.replace(prefix+'_', '')for p in plot_options]
-
-
- def show(self, fig):
- with self.cols[1]:
- st.plotly_chart(fig)
-
- def st_plot_scatter2D(self, df=None):
- df = df if isinstance(df, pd.DataFrame) else self.df
- column_options = list(df.columns)
-
-
- with self.cols[0]:
- st.markdown("## X Axis")
- x_col = st.selectbox("X Axis",column_options, 0 )
-
- st.markdown("## Y Axis")
- y_col = st.selectbox("Y Axis", column_options, 1)
-
- st.markdown("## Color Axis")
- color_col = st.selectbox("Color", column_options + [None], 0)
- color_args = {"color": color_col} if color_col is not None else {}
- marker_size = st.slider("Select Marker Size", 5, 30, 20)
-
- df["size"] = [marker_size for _ in range(len(df))]
-
-
- fig = px.scatter(df, x=x_col, y=y_col, size="size", **color_args)
- fig.update_layout(width=1000,
- height=800)
-
- return fig
-
-
-
-
- def st_plot_scatter3D(self, df=None):
- df = df if isinstance(df, pd.DataFrame) else self.df
- column_options = list(df.columns)
-
- plotly_kwargs = {}
- with self.cols[0]:
- st.markdown("## X Axis")
- plotly_kwargs['x'] = st.selectbox("X Axis", column_options, 0)
- st.markdown("## Y Axis")
- plotly_kwargs['y'] = st.selectbox("Y Axis", column_options, 1)
- st.markdown("## Z Axis")
- plotly_kwargs['z'] = st.selectbox("Z Axis", column_options, 2)
- st.markdown("## Color Axis")
- plotly_kwargs['color'] = st.selectbox("## Color", [None] + column_options, 0)
- marker_size = st.slider("Select Marker Size", 5, 30, 20)
- df["size"] = [marker_size for _ in range(len(df))]
- plotly_kwargs['size']= 'size'
- plotly_kwargs['template'] = self.theme
-
- fig = px.scatter_3d(df, **plotly_kwargs)
- fig.update_layout(width=self.width, height=self.height, font_size=15)
- return fig
-
-
- def st_plot_box(self, df=None):
-
-
- df = df if isinstance(df, pd.DataFrame) else self.df
- column_options = list(df.columns)
- plotly_kwargs = {}
-
- with self.cols[0]:
- st.markdown("## X Axis")
- plotly_kwargs['x'] = st.selectbox("X Axis", column_options, 0)
- st.markdown("## Y Axis")
- plotly_kwargs['y'] = st.selectbox("Y Axis", column_options, 1)
- st.markdown("## Color Axis")
- plotly_kwargs['color'] = st.selectbox("Color", [None] + column_options, 0)
- marker_size = st.slider("Select Marker Size", 5, 30, 20)
- df["size"] = [marker_size for _ in range(len(df))]
- plotly_kwargs['template'] = self.theme
- st.markdown("## Box Group Mode")
- plotly_kwargs['boxmode'] = st.selectbox("Choose Box Mode", ["group", "overlay"], 0)
-
- # df[ plotly_kwargs['x']] = df[ plotly_kwargs['x']].apply(lambda x: str(x))
-
-
- fig = px.box(df, **plotly_kwargs)
- fig.update_layout(width=self.width, height=self.height, font_size=20)
- return fig
-
- def st_plot_bar(self, df=None):
-
- df = df if isinstance(df, pd.DataFrame) else self.df
- column_options = list(df.columns)
-
-
- plot_kwargs = {}
- with self.cols[0]:
-
-
- st.markdown("## X Axis")
- plot_kwargs['x'] = st.selectbox("X Axis",column_options , 0 )
-
- st.markdown("## Y Axis")
- plot_kwargs['y'] = st.selectbox("Y Axis", column_options, 0)
- plot_kwargs['barmode'] = st.selectbox("Choose Bar Mode", ["relative", "group", "overlay"], 1)
-
- st.markdown("## Color Axis")
- plot_kwargs['color'] = st.selectbox("Color", [None] + column_options, 0 )
-
- fig = px.bar(df, **plot_kwargs)
-
- fig.update_layout(width=self.width, height=self.height, font_size=20)
- return fig
-
-
-
-
- def st_plot_histogram(self, df=None):
-
- df = df if isinstance(df, pd.DataFrame) else self.df
- column_options = list(df.columns)
- # Choose X, Y and Color Axis
- with self.cols[0]:
- plot_kwargs = {}
- st.markdown("### X-axis")
- plot_kwargs['x'] = st.selectbox("Choose X-Axis Feature", column_options, 0)
- # plot_kwargs['nbins'] = st.slider("Number of Bins", 10, 1000, 10)
-
- st.markdown("### Y-axis")
- plot_kwargs['y'] = st.selectbox("Choose Y-Axis Feature", [None]+ column_options, 0)
-
- st.markdown("## Color Axis")
- plot_kwargs['color'] = st.selectbox("Color", [None]+ column_options , 0 )
- # color_args = {"color":color_col} if color_col is not None else {}
-
- plot_kwargs['barmode'] = st.selectbox("Choose Bar Mode", ["relative", "group", "overlay"], 2)
-
-
-
- fig = px.histogram(df, **plot_kwargs)
- fig.update_layout(width=self.width, height=self.height, font_size=20)
- return fig
-
-
- def st_plot_heatmap(cls, df=None):
-
- df = df if isinstance(df, pd.DataFrame) else self.df
- column_options = list(df.columns)
- # Choose X, Y and Color Axis
-
- plotly_kwargs = {}
- with cls.cols[0]:
- st.markdown("### X-axis")
- plotly_kwargs['x'] = st.selectbox("Choose X-Axis Feature", column_options, 0)
- plotly_kwargs['nbinsx'] = st.slider("Number of Bins", 10, 100, 10)
-
- st.markdown("### Y-axis")
- plotly_kwargs['y'] = st.selectbox("Choose Y-Axis Feature", [None]+column_options, 0)
- plotly_kwargs['nbinsy'] = st.slider("Number of Bins (Y-Axis)", 10, 100, 10)
-
- st.markdown("### Z-axis")
- plotly_kwargs['z'] = st.selectbox("Choose Z-Axis Feature", column_options, 0)
- plotly_kwargs['histfunc'] = st.selectbox("Aggregation Function", ["avg", "sum", "min", "sum", "count"], 0)
- plotly_kwargs['template'] = cls.theme
-
- fig = px.density_heatmap(df, **plotly_kwargs)
- fig.update_layout(width=cls.width, height=cls.height, font_size=20)
-
-
-
- return fig
-
-
- @classmethod
- def process_kwargs(cls, kwargs:dict, fn_schema:dict):
-
- for k,v in kwargs.items():
- if v == 'None':
- v = None
-
- if isinstance(v, str):
- if v.startswith('[') and v.endswith(']'):
- if len(v) > 2:
- v = eval(v)
- else:
- v = []
-
- elif v.startswith('{') and v.endswith('}'):
-
- if len(v) > 2:
- v = c.jload(v)
- else:
- v = {}
- elif k in fn_schema['input'] and fn_schema['input'][k] == 'str':
- if v.startswith("f'") or v.startswith('f"'):
- v = c.ljson(v)
- else:
- v = v
-
- elif k == 'kwargs':
- continue
- elif v == 'NA':
- assert k != 'NA', f'Key {k} not in default'
- elif v in ['True', 'False']:
- v = eval(v)
- else:
- try:
- v = eval(v)
- except:
- pass
-
- kwargs[k] = v
- return kwargs
-
-
-
-
- @classmethod
- def style2path(cls, style:str=None) -> str:
- path = cls.dirpath() + '/styles'
- style2path = {p.split('/')[-1].split('.')[0] : p for p in cls.ls(path)}
- if style != None:
- return style2path[style]
- return style2path
-
-
- @classmethod
- def load_style(cls, style='commune'):
- style_path = cls.style2path(style)
- with open(style_path) as f:
- st.markdown(f"", unsafe_allow_html=True)
-
- @classmethod
- def line_seperator(cls, text='-', length=50):
- st.write(text*length)
-
- @classmethod
- def function2streamlit(cls,
- module = None,
- fn:str = '__init__',
- extra_defaults:dict=None,
- cols:list=None,
- skip_keys = ['self', 'cls'],
- mode = 'pm2'):
-
- key_prefix = f'{module}.{fn}'
- if module == None:
- module = cls
-
- elif isinstance(module, str):
- module = c.module(module)
-
- config = module.config(to_munch=False)
-
- fn_schema = module.schema(defaults=True, include_parents=True)[fn]
-
- if fn == '__init__':
- extra_defaults = config
- elif extra_defaults is None:
- extra_defaults = {}
-
- kwargs = {}
- fn_schema['default'].pop('self', None)
- fn_schema['default'].pop('cls', None)
- fn_schema['default'].update(extra_defaults)
- fn_schema['default'].pop('config', None)
- fn_schema['default'].pop('kwargs', None)
-
-
- fn_schema['input'].update({k:str(type(v)).split("'")[1] for k,v in extra_defaults.items()})
- if cols == None:
- cols = [1 for i in list(range(int(len(fn_schema['input'])**0.5)))]
- cols = st.columns(cols)
-
-
- for i, (k,v) in enumerate(fn_schema['default'].items()):
-
- optional = fn_schema['default'][k] != 'NA'
- fn_key = k
- if fn_key in skip_keys:
- continue
- if k in fn_schema['input']:
- k_type = fn_schema['input'][k]
- if 'Munch' in k_type or 'Dict' in k_type:
- k_type = 'Dict'
- if k_type.startswith('typing'):
- k_type = k_type.split('.')[-1]
- fn_key = f'**{k} ({k_type}){"" if optional else "(REQUIRED)"}**'
- col_idx = i
- if k in ['kwargs', 'args'] and v == 'NA':
- continue
-
-
-
- col_idx = col_idx % (len(cols))
- kwargs[k] = cols[col_idx].text_input(fn_key, v, key=f'{key_prefix}.{k}')
-
- kwargs = cls.process_kwargs(kwargs, fn_schema)
-
- return kwargs
-
- @classmethod
- def st_metrics_dict(cls, x:str, num_columns=3):
- cols = st.columns(num_columns)
- for i, (k,v) in enumerate(x.items()):
- if type(v) in [int, float, str]:
- cols[i % num_columns].metric(label=k, value=v)
-
- @classmethod
- def styles(cls):
- return list(cls.style2path().keys())
-
-
- @classmethod
- def style_paths(cls):
- return list(cls.style2path().values())
-
-
-
- def add_plot_tools(self):
- # sync plots from express
- for fn_name in dir(px):
- if not (fn_name.startswith('__') and fn_name.endswith('__')):
- plt_obj = getattr(px, fn_name)
- if callable(plt_obj):
- setattr(self, fn_name, plt_obj)
-
- # self.dag = DagModule()
-
- @staticmethod
- def local_css(file_name=os.path.dirname(__file__)+'/style.css'):
- import streamlit as st
-
-
- with open(file_name) as f:
- st.markdown(f"", unsafe_allow_html=True)
-
-
- @staticmethod
- def metrics_dict(x, num_rows:int = 1):
- num_elements = len(x)
- num_cols = num_elements//num_rows
- row_cols = [st.columns(num_cols) for i in range(num_rows)]
- for i in range(num_elements):
- k = list(x.keys())[i]
- v = list(x.values())[i]
- row_idx = i//num_cols
- col_idx = i%num_cols
- row_cols[row_idx][col_idx].metric(k, int(v))
-
- def filter_dataframe(df: pd.DataFrame) -> pd.DataFrame:
-
- from pandas.api.types import (
- is_categorical_dtype,
- is_datetime64_any_dtype,
- is_numeric_dtype,
- is_object_dtype,
- )
- import pandas as pd
- import streamlit as st
-
- """
- Adds a UI on top of a dataframe to let viewers filter columns
-
- Args:
- df (pd.DataFrame): Original dataframe
-
- Returns:
- pd.DataFrame: Filtered dataframe
- """
- modify = st.checkbox("Add filters")
-
- if not modify:
- return df
-
- df = df.copy()
-
- # Try to convert datetimes into a standard format (datetime, no timezone)
- for col in df.columns:
- if is_object_dtype(df[col]):
- try:
- df[col] = pd.to_datetime(df[col])
- except Exception:
- pass
-
- if is_datetime64_any_dtype(df[col]):
- df[col] = df[col].dt.tz_localize(None)
-
- modification_container = st.container()
-
- with modification_container:
- to_filter_columns = st.multiselect("Filter dataframe on", df.columns)
- for column in to_filter_columns:
- left, right = st.columns((1, 20))
- # Treat columns with < 10 unique values as categorical
- if is_categorical_dtype(df[column]) or df[column].nunique() < 10:
- user_cat_input = right.multiselect(
- f"Values for {column}",
- df[column].unique(),
- default=list(df[column].unique()),
- )
- df = df[df[column].isin(user_cat_input)]
- elif is_numeric_dtype(df[column]):
- _min = float(df[column].min())
- _max = float(df[column].max())
- step = (_max - _min) / 100
- user_num_input = right.slider(
- f"Values for {column}",
- min_value=_min,
- max_value=_max,
- value=(_min, _max),
- step=step,
- )
- df = df[df[column].between(*user_num_input)]
- elif is_datetime64_any_dtype(df[column]):
- user_date_input = right.date_input(
- f"Values for {column}",
- value=(
- df[column].min(),
- df[column].max(),
- ),
- )
- if len(user_date_input) == 2:
- user_date_input = tuple(map(pd.to_datetime, user_date_input))
- start_date, end_date = user_date_input
- df = df.loc[df[column].between(start_date, end_date)]
- else:
- user_text_input = right.text_input(
- f"Substring or regex in {column}",
- )
- if user_text_input:
- df = df[df[column].astype(str).str.contains(user_text_input)]
-
- return df
\ No newline at end of file
diff --git a/commune/modules/streamlit/streamlit_module.yaml b/commune/modules/streamlit/streamlit_module.yaml
deleted file mode 100755
index aa865a578..000000000
--- a/commune/modules/streamlit/streamlit_module.yaml
+++ /dev/null
@@ -1 +0,0 @@
-module: subspace
\ No newline at end of file
diff --git a/commune/modules/subprocess/subprocess_module.py b/commune/modules/subprocess/subprocess_module.py
deleted file mode 100644
index a2b8c3f04..000000000
--- a/commune/modules/subprocess/subprocess_module.py
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-import os, sys
-from commune import Module
-from commune.utils import *
-import shlex
-import subprocess
-
-class SubprocessModule(Module):
- subprocess_map = {}
- def __init__(self, config=None, **kwargs):
- Module.__init__(self, config=config)
- self.subprocess_map_path = self.cache_path
-
- def __reduce__(self):
- deserializer = self.__class__
- serialized_data = (self.config,)
- return deserializer, serialized_data
-
- def submit(command):
- return self.run_command(command)
-
- @property
- def subprocess_map(self):
- self.load_cache()
- return self.cache
-
- def rm_subprocess(self, key):
- subprocess_dict = self.subprocess_map[key]
- pid = subprocess_dict['pid']
- try:
- self.kill_pid(pid)
- except ProcessLookupError:
- pass
- self.pop_cache(key)
-
- return pid
-
- rm = rm_subprocess
-
- def rm_all(self):
- rm_dict = {}
- for k in self.list_keys():
- rm_dict[k] = self.rm(key=k, load=False, save=False)
-
- return rm_dict
-
- def add_subprocess(self, command:str,key=None, cache=True, add_info={}):
-
- process = subprocess.Popen(shlex.split(command))
- process_state_dict = process.__dict__
- # process_state_dict.pop('_waitpid_lock')
-
- subprocess_dict = {k:v for k,v in process_state_dict.items() if k != '_waitpid_lock'}
- if cache == True:
- if key == None or key == 'pid':
- key= str(process.pid)
- subprocess_dict = dict_override(subprocess_dict, add_info)
- self.put_cache(key, subprocess_dict)
-
- return subprocess_dict
-
- submit = add = add_subprocess
-
- def ls(self):
- self.load_state()
- return list(self.subprocess_map.keys())
-
- ls_keys = list_keys = list = ls
-
-
- @property
- def portConnection( port : int, host='0.0.0.0'):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- result = s.connect_ex((host, port))
- if result == 0: return True
- return False
-
- @classmethod
- def streamlit(cls):
- st.write(cls().subprocess_map)
-
-if __name__ == "__main__":
- SubprocessModule.run()
- # import stre=amlit as st
- # module = SubprocessModule.deploy(actor=False, override={'refresh':True})
- # st.write(module)
- # import ray
-
- # # st.write(module.subprocess_map)
-
- # module.client.rest
-
-
- # st.write(ray.get(module.ls.remote()))
- # st.write(ray.get(module.rm_all.remote()))
- # st.write(module.add(key='pid', command='python commune/gradio/api/module.py --module="gradio.client.module.ClientModule"'))
- # st.write(module.getattr('cache'))
- # st.write(ray.get(module.ls.remote()))
-
-
-
diff --git a/commune/modules/subspace/README.md b/commune/modules/subspace/README.md
deleted file mode 100644
index 1f7258b08..000000000
--- a/commune/modules/subspace/README.md
+++ /dev/null
@@ -1,113 +0,0 @@
-# Subspace Module
-
-This involves a runthrough of the main function of subspace. We recommend going through the code if you want to understand the full extent of this module as there are alot of functions
-
-## Register a Module
-To register a module, you can use the following command
-
-```
-c model.openai register tag=sup api_key=sk-...
-```
-
-or
-
-```
-c register model.openai tag=sup api_key=sk-...
-```
-
-Please make sure you specify a unique tag, as it will not go through if someone else has that name on the subnet. When you deploy the module, the module will be serving locally on your machine and will be accessed by the network.
-
-
-## Update a Module
-
-To update a module, you can use the following command. At the moment you can update the module's name and address. Please not if you update the name, you will need to restart the server with the new name. This is currently something we want to avoid in the future by having to rename the server without killing it
-
-```
-
-c update_module model.openai name=model.openai::fam1 address=124.545.545:8080
-```
-
-
-
-## Check Stats
-
-To check the stats of a module, you can use the following command
-
-```
-c stats
-```
-
-If you want to sync the stats with the network, you can use the following.
-
-```
-c stats update=True
-```
-
-
-
-## Transfer Tokens
-
-To tranfer tokens to a module, you can use the following command
-
-```
-c transfer model.openai 100 model.openai.2
-```
-or you an specify the address, this is the safer way to do it, as you can accidentally send it to the wrong address if the name has changed on the network.
-
-```
-c transfer ADDRESS_FROM model.openai 100 ADDRESS_TO
-```
-
-## Stake Tokens
-
-To stake on a module, you can use the following command
-
-```
-c stake model.openai amount=100
-```
-
-To unstake on a module, you can use the following command
-
-```
-c unstake model.openai amount=100
-```
-
-### Staking on another Module with your Tokens
-
-To stake on another module with your tokens, you can use the following command.
-
-```
-
-c stake key=model.openai amount=100 module_key=model.openai.2
-```
-
-### Unstaking on another Module with your Tokens
-
-To unstake on another module with your tokens, you can use the following command
-
-```
-c unstake key=model.openai amount=100 module_key=model.openai.2
-```
-
-## Start Local Node
-
-To start a local node, you can use the following command
-
-```
-c start_node alice chain=main
-```
-This starts a node with the name alice on the main chain. You can also specify the chain to be main or dev.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/commune/modules/subspace/__init__.py b/commune/modules/subspace/__init__.py
deleted file mode 100644
index bc4ebdc34..000000000
--- a/commune/modules/subspace/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-
-# Substrate ss58_format
-__ss58_format__ = 42
-
-# The MIT License (MIT)
-# Copyright © 2021 Yuma Rao
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-import argparse
-import copy
-import os
-from .balance import Balance
-
diff --git a/commune/modules/subspace/balance.py b/commune/modules/subspace/balance.py
deleted file mode 100644
index 81713df26..000000000
--- a/commune/modules/subspace/balance.py
+++ /dev/null
@@ -1,19 +0,0 @@
-
-from typing import Union
-import commune as c
-
-class Balance:
- decimals = 9
- def __init__(self, nano: float, decimals=decimals):
- self.nano = nano
- self.joules = self.from_nano(nano)
-
- @classmethod
- def from_nano(cls, amount: int):
- """Given nano (int), return Balance object with nano(int) and joules(float), where nano = int(joules*pow(10,9))"""
- return amount / (10 ** cls.decimals)
-
- @classmethod
- def to_nano(cls, amount: int):
- """Given nano (int), return Balance object with nano(int) and joules(float), where nano = int(joules*pow(10,9))"""
- return amount * (10 ** cls.decimals)
diff --git a/commune/modules/subspace/chain.py b/commune/modules/subspace/chain.py
deleted file mode 100644
index 73b217fbe..000000000
--- a/commune/modules/subspace/chain.py
+++ /dev/null
@@ -1,512 +0,0 @@
-
-import torch
-import scalecodec
-from retry import retry
-from typing import List, Dict, Union, Optional, Tuple
-from substrateinterface import SubstrateInterface
-import commune as c
-from typing import List, Dict, Union, Optional, Tuple
-from commune.utils.network import ip_to_int, int_to_ip
-from rich.prompt import Confirm
-from commune.modules.subspace.balance import Balance
-from commune.modules.subspace.utils import (U16_NORMALIZED_FLOAT,
- U64_MAX,
- NANOPERTOKEN,
- U16_MAX,
- is_valid_address_or_public_key,
- )
-from commune.modules.subspace.chain_data import (ModuleInfo, custom_rpc_type_registry)
-
-import streamlit as st
-import json
-from loguru import logger
-import os
-logger = logger.opt(colors=True)
-
-
-
-class Subspace(c.Module):
- """
- Handles interactions with the subspace chain.
- """
- fmt = 'j'
- whitelist = []
- chain_name = 'subspace'
- default_config = c.get_config(chain_name, to_munch=False)
- token_decimals = default_config['token_decimals']
- network = default_config['network']
- chain = network
- chain_path = c.libpath + '/subspace'
- spec_path = f"{chain_path}/specs"
- netuid = default_config['netuid']
- mode = default_config['mode']
-
- @classmethod
- def get_node_id(cls, node='alice',
- chain=chain,
- max_trials=10,
- sleep_interval=1,
- mode=mode,
- verbose=True
- ):
- node2path = cls.node2path(chain=chain)
- node_path = node2path[node]
- node_id = None
- node_logs = ''
- indicator = 'Local node identity is: '
-
- while indicator not in node_logs and max_trials > 0:
- if mode == 'docker':
- node_path = node2path[node]
- node_logs = c.module('docker').logs(node_path)
- elif mode == 'local':
- node_logs = c.logs(node_path, start_line = 0 , end_line=400, mode='local')
- else:
- raise Exception(f'Invalid mode {mode}')
-
- if indicator in node_logs:
- break
- max_trials -= 1
- c.sleep(sleep_interval)
- for line in node_logs.split('\n'):
- # c.print(line)
- if 'Local node identity is: ' in line:
- node_id = line.split('Local node identity is: ')[1].strip()
- break
-
- if node_id == None:
- raise Exception(f'Could not find node_id for {node} on {chain}')
-
- return node_id
-
-
-
- @classmethod
- def start_node(cls,
- node : str,
- chain:int = network,
- port:int=None,
- rpc_port:int=None,
- ws_port:int=None,
- telemetry_url:str = 'wss://telemetry.gpolkadot.io/submit/0',
- purge_chain:bool = True,
- refresh:bool = False,
- verbose:bool = False,
- boot_nodes = None,
- node_key = None,
- mode :str = mode,
- rpc_cors = 'all',
- validator:bool = False,
-
- ):
-
- ip = c.ip()
-
- node_info = c.locals2kwargs(locals())
-
- cmd = cls.chain_release_path()
-
- free_ports = c.free_ports(n=3)
-
- if port == None:
- node_info['port'] = port = free_ports[0]
-
- if rpc_port == None:
- node_info['rpc_port'] = rpc_port = free_ports[1]
- if ws_port == None:
- node_info['ws_port'] = ws_port = free_ports[2]
- # resolve base path
- base_path = cls.resolve_base_path(node=node, chain=chain)
-
- # purge chain
- if purge_chain:
- cls.purge_chain(base_path=base_path)
-
- cmd_kwargs = f' --base-path {base_path}'
-
- chain_spec_path = cls.chain_spec_path(chain)
- cmd_kwargs += f' --chain {chain_spec_path}'
-
-
- if validator :
- cmd_kwargs += ' --validator'
- else:
- cmd_kwargs += ' --ws-external --rpc-external'
- cmd_kwargs += f' --port {port} --rpc-port {rpc_port} --ws-port {ws_port}'
-
- chain_info = cls.getc(f'chain_info.{chain}', {})
- boot_nodes = chain_info.get('boot_nodes', [])
- chain_info['nodes'] = chain_info.get('nodes', {})
- chain_info['nodes'][node] = node_info
- boot_nodes = chain_info['boot_nodes'] = chain_info.get('boot_nodes', [])
-
- # add the node to the boot nodes
- if len(boot_nodes) > 0:
- node_info['boot_nodes'] = c.choice(boot_nodes) # choose a random boot node (at we chose one)
- cmd_kwargs += f" --bootnodes {node_info['boot_nodes']}"
-
- if node_key != None:
- cmd_kwargs += f' --node-key {node_key}'
-
- cmd_kwargs += f' --rpc-cors={rpc_cors}'
-
- name = f'{cls.node_prefix()}.{chain}.{node}'
-
- c.print(f'Starting node {node} for chain {chain} with name {name} and cmd_kwargs {cmd_kwargs}')
-
- if mode == 'local':
- #
- cmd = c.pm2_start(path=cls.chain_release_path(mode=mode),
- name=name,
- cmd_kwargs=cmd_kwargs,
- refresh=refresh,
- verbose=verbose)
-
- elif mode == 'docker':
-
- # run the docker image
- volumes = f'-v {base_path}:{base_path} -v {cls.spec_path}:/subspace/specs'
- net = '--net host'
- c.cmd('docker run -d --name {name} {net} {volumes} subspace bash -c "{cmd}"', verbose=verbose)
- else:
- raise Exception(f'unknown mode {mode}')
-
- if validator:
- # ensure you add the node to the chain_info if it is a bootnode
- node_id = cls.get_node_id(node=node, chain=chain, mode=mode)
- chain_info['boot_nodes'] += [f'/ip4/{ip}/tcp/{node_info["port"]}/p2p/{node_id}']
- chain_info['nodes'][node] = node_info
- cls.putc(f'chain_info.{chain}', chain_info)
-
-
- return {'success':True, 'msg': f'Node {node} is not a validator, so it will not be added to the chain'}
-
-
- @classmethod
- def start_nodes(self, node='node', n=10, chain=chain, **kwargs):
- nodes = self.nodes(chain=chain)
- for node in nodes:
- self.start_node(node=node, chain=chain, **kwargs)
-
-
-
- @classmethod
- def start_chain(cls,
- chain:str=chain,
- n_valis:int = 8,
- n_nonvalis:int = 16,
- verbose:bool = False,
- purge_chain:bool = True,
- refresh: bool = True,
- trials:int = 3,
- reuse_ports: bool = False,
- port_keys: list = ['port', 'rpc_port', 'ws_port'],
- ):
-
- # KILL THE CHAIN
- if refresh:
- c.print(f'KILLING THE CHAIN ({chain})', color='red')
- cls.kill_chain(chain=chain)
-
-
- ## VALIDATOR NODES
- vali_node_keys = cls.vali_node_keys(chain=chain)
- vali_nodes = list(cls.vali_node_keys(chain=chain).keys())
- if n_valis != -1:
- vali_nodes = vali_nodes[:n_valis]
- vali_node_keys = {k: vali_node_keys[k] for k in vali_nodes}
- assert len(vali_nodes) >= 2, 'There must be at least 2 vali nodes'
- # BUILD THE CHAIN SPEC AFTER SELECTING THE VALIDATOR NODES
- cls.build_spec(chain=chain, verbose=verbose, vali_node_keys=vali_node_keys)
-
- ## NON VALIDATOR NODES
- nonvali_node_keys = cls.nonvali_node_keys(chain=chain)
- nonvali_nodes = list(cls.nonvali_node_keys(chain=chain).keys())
- if n_nonvalis != -1:
- nonvali_nodes = nonvali_nodes[:n_valis]
- nonvali_node_keys = {k: nonvali_node_keys[k] for k in nonvali_nodes}
-
- # refresh the chain info in the config
-
-
- existing_node_ports = {'vali': [], 'nonvali': []}
-
- if reuse_ports:
- node_infos = cls.getc(f'chain_info.{chain}.nodes')
- for node, node_info in node_infos.items():
- k = 'vali' if node_info['validator'] else 'nonvali'
- existing_node_ports[k].append([node_info[pk] for pk in port_keys])
-
- if refresh:
- # refresh the chain info in the config
- cls.putc(f'chain_info.{chain}', {'nodes': {}, 'boot_nodes': [], 'url': []})
-
- avoid_ports = []
-
- # START THE VALIDATOR NODES
- for node in (vali_nodes + nonvali_nodes):
- c.print(f'Starting node {node} for chain {chain}')
- name = f'{cls.node_prefix()}.{chain}.{node}'
-
- # BUILD THE KWARGS TO CREATE A NODE
-
- node_kwargs = {
- 'chain':chain,
- 'node':node,
- 'verbose':verbose,
- 'purge_chain': purge_chain,
- 'validator': bool(node in vali_nodes),
- }
-
- # get the ports for (port, rpc_port, ws_port)
- # if we are reusing ports, then pop the first ports from the existing_node_ports
- node_ports= []
- node_type = 'vali' if node_kwargs['validator'] else 'nonvali'
- if len(existing_node_ports[node_type]) > 0:
- node_ports = existing_node_ports[node_type].pop(0)
- else:
- node_ports = c.free_ports(n=3, avoid_ports=avoid_ports)
- assert len(node_ports) == 3, f'node_ports must be of length 3, not {len(node_ports)}'
-
- for k, port in zip(port_keys, node_ports):
- avoid_ports.append(port)
- node_kwargs[k] = port
-
-
- fails = 0
- while trials > fails:
- try:
- cls.start_node(**node_kwargs, refresh=refresh)
- break
- except Exception as e:
- c.print(f'Error starting node {node} for chain {chain}, {e}', color='red')
- fails += 1
- raise e
- continue
-
-
- @classmethod
- def vali_nodes(cls, chain=chain):
- return cls.nodes(mode='vali', chain=chain)
-
-
- @classmethod
- def nonvali_nodes(cls, chain=chain):
- return cls.nodes(mode='nonvali', chain=chain)
-
-
- @classmethod
- def vali_node_keys(cls,chain=chain):
- return {k:v for k,v in cls.node_keys(chain=chain).items() if k.startswith('vali')}
-
- @classmethod
- def nonvali_node_keys(self,chain=chain):
- return {k:v for k,v in self.node_keys(chain=chain).items() if k.startswith('nonvali')}
-
-
- @classmethod
- def node_key_exists(cls, node='alice', chain=chain):
- return len(cls.node_key_paths(node=node, chain=chain)) > 0
-
-
- @classmethod
- def add_node_key(cls,
- node:str,
- mode: str = 'nonvali',
- chain = chain,
- tag_seperator = '_',
- refresh: bool = False,
- ):
- '''
- adds a node key
- '''
- cmds = []
-
- assert mode in ['vali', 'nonvali'], f'Unknown mode {mode}, must be one of vali, nonvali'
- node = str(node)
-
- c.print(f'adding node key {node} for chain {chain}')
-
- node = c.copy(f'{mode}{tag_seperator}{node}')
-
-
- chain_path = cls.chain_release_path(mode='local')
-
- for key_type in ['gran', 'aura']:
-
- if key_type == 'gran':
- schema = 'Ed25519'
- elif key_type == 'aura':
- schema = 'Sr25519'
-
- key_path = f'{cls.node_key_prefix}.{chain}.{node}.{key_type}'
-
- key = c.get_key(key_path,crypto_type=schema, refresh=refresh)
-
- base_path = cls.resolve_base_path(node=node, chain=chain)
-
-
- cmd = f'''{chain_path} key insert --base-path {base_path} --chain {chain} --scheme {schema} --suri "{key.mnemonic}" --key-type {key_type}'''
-
- cmds.append(cmd)
-
- for cmd in cmds:
- # c.print(cmd)
- # volumes = f'-v {base_path}:{base_path}'
- # c.cmd(f'docker run {volumes} subspace {cmd} ', verbose=True)
- c.cmd(cmd, verbose=True, cwd=cls.chain_path)
-
- return {'success':True, 'node':node, 'chain':chain, 'keys':cls.get_node_key(node=node, chain=chain, mode=mode)}
-
-
-
- @classmethod
- def purge_chain(cls,
- base_path:str = None,
- chain:str = chain,
- node:str = 'alice',
- sudo = False):
- if base_path == None:
- base_path = cls.resolve_base_path(node=node, chain=chain)
-
- return c.rm(base_path+'/chains/commune/db')
-
- @classmethod
- def chain_target_path(self, chain:str = chain):
- return f'{self.chain_path}/target/release/node-subspace'
-
-
- @classmethod
- def build_runtime(cls, verbose:bool=True, mode=mode):
- if mode == 'docker':
- c.module('docker').build(cls.chain_name)
- elif mode == 'local':
- c.cmd('cargo build --release --locked', cwd=cls.chain_path, verbose=verbose)
- else:
- raise ValueError(f'Unknown mode {mode}, must be one of docker, local')
-
- @classmethod
- def chain_release_path(cls, mode='local'):
-
- if mode == 'docker':
- chain_path = f'/subspace'
- elif mode == 'local':
- chain_path = cls.chain_path
- else:
- raise ValueError(f'Unknown mode {mode}, must be one of docker, local')
- path = f'{chain_path}/target/release/node-subspace'
- return path
-
-
-
- @classmethod
- def resolve_base_path(cls, node='alice', chain=chain):
- return cls.resolve_path(f'nodes/{chain}/{node}')
-
- @classmethod
- def resolve_node_keystore_path(cls, node='alice', chain=chain):
- path = cls.resolve_base_path(node=node, chain=chain) + f'/chains/commune/keystore'
- if not c.exists(path):
- c.mkdir(path)
- return path
-
- @classmethod
- def build_spec(cls,
- chain = chain,
- disable_default_bootnode: bool = True,
- snap:bool = False,
- verbose:bool = True,
- vali_node_keys:dict = None,
- mode = mode,
- ):
-
- if snap:
- cls.snap()
-
- chain_spec_path = cls.chain_spec_path(chain)
- chain_release_path = cls.chain_release_path(mode=mode)
-
- cmd = f'{chain_release_path} build-spec --chain {chain}'
-
- if disable_default_bootnode:
- cmd += ' --disable-default-bootnode'
- cmd += f' > {chain_spec_path}'
-
- # chain_spec_path_dir = os.path.dirname(chain_spec_path)
- c.print(cmd)
- if mode == 'docker':
- volumes = f'-v {cls.spec_path}:{cls.spec_path}'
- c.cmd(f'docker run {volumes} subspace bash -c "{cmd}"')
- elif mode == 'local':
- c.cmd(f'bash -c "{cmd}"', cwd=cls.chain_path, verbose=True)
-
-
- # ADD THE VALI NODE KEYS
-
- if vali_node_keys == None:
- vali_node_keys = cls.vali_node_keys(chain=chain)
- spec = c.get_json(chain_spec_path)
- spec['genesis']['runtime']['aura']['authorities'] = [k['aura'] for k in vali_node_keys.values()]
- spec['genesis']['runtime']['grandpa']['authorities'] = [[k['gran'],1] for k in vali_node_keys.values()]
- c.put_json(chain_spec_path, spec)
- resp = {'spec_path': chain_spec_path, 'spec': spec}
- return {'success':True, 'message':'built spec', 'chain':chain}
-
-
- @classmethod
- def chain_specs(cls):
- return c.ls(f'{cls.spec_path}/')
-
- @classmethod
- def chain2spec(cls, chain = None):
- chain2spec = {os.path.basename(spec).replace('.json', ''): spec for spec in cls.specs()}
- if chain != None:
- return chain2spec[chain]
- return chain2spec
-
- specs = chain_specs
- @classmethod
- def get_spec(cls, chain:str=chain):
- chain = cls.chain_spec_path(chain)
-
- return c.get_json(chain)
-
-
- @classmethod
- def spec_exists(cls, chain):
- return c.exists(f'{cls.spec_path}/{chain}.json')
-
-
-
- @classmethod
- def chain_spec_path(cls, chain = None):
- if chain == None:
- chain = cls.network
- return cls.spec_path + f'/{chain}.json'
-
-
- @classmethod
- def new_chain_spec(self,
- chain,
- base_chain:str = chain,
- balances : 'List[str, int]' = None,
- aura_authorities: 'List[str, int]' = None,
- grandpa_authorities: 'List[str, int]' = None,
- ):
- base_spec = self.get_spec(base_chain)
- new_chain_path = f'{self.spec_path}/{chain}.json'
-
- if balances != None:
- base_spec['balances'] = balances
- if aura_authorities != None:
- base_spec['balances'] = aura_authorities
- c.put_json( new_chain_path, base_spec)
-
- return base_spec
-
- new_chain = new_chain_spec
-
- @classmethod
- def rm_chain(self, chain):
- return c.rm(self.chain_spec_path(chain))
-
\ No newline at end of file
diff --git a/commune/modules/subspace/chain_data.py b/commune/modules/subspace/chain_data.py
deleted file mode 100644
index 7af623b27..000000000
--- a/commune/modules/subspace/chain_data.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# The MIT License (MIT)
-# Copyright © 2023 Opentensor Foundation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
-# the Software.
-
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-from dataclasses import dataclass
-from typing import List, Tuple, Dict, Optional, Any
-import commune
-from commune.modules.subspace import Balance
-import torch
-from scalecodec.base import RuntimeConfiguration, ScaleBytes
-from scalecodec.type_registry import load_type_registry_preset
-from scalecodec.utils.ss58 import ss58_encode
-from enum import Enum
-
-
-custom_rpc_type_registry = {
- "types": {
- "SubnetInfo": {
- "type": "struct",
- "type_mapping": [
- ["netuid", "Compact"],
- ["immunity_period", "Compact"],
- ["min_allowed_weights", "Compact"],
- ["max_weights_limit", "Compact"],
- ["subnetwork_n", "Compact"],
- ["max_allowed_uids", "Compact"],
- ["blocks_since_last_step", "Compact"],
- ["tempo", "Compact"],
- ]
- },
- "ModuleInfo": {
- "type": "struct",
- "type_mapping": [
- ["key", "AccountId"],
- ["uid", "Compact"],
- ["netuid", "Compact"],
- ["name", "Vec"],
- ["active", "bool"],
- ["stake", "Vec<(AccountId, Compact)>"],
- ["rank", "Compact"],
- ["emission", "Compact"],
- ["incentive", "Compact"],
- ["dividends", "Compact"],
- ["last_update", "Compact"],
- ["weights", "Vec<(Compact, Compact)>"],
- ["bonds", "Vec<(Compact, Compact)>"],
- ],
- },
-
- }
-}
-
-class ChainDataType(Enum):
- ModuleInfo = 1
- SubnetInfo = 2
-# Constants
-NANOPERTOKEN = 1e9
-U8_MAX = 255
-U16_MAX = 65535
-U32_MAX = 4294967295
-U64_MAX = 18446744073709551615
-U128_MAX = 340282366920938463463374607431768211455
-def from_scale_encoding( vec_u8: List[int], type_name: ChainDataType, is_vec: bool = False, is_option: bool = False ) -> Optional[Dict]:
- as_bytes = bytes(vec_u8)
- as_scale_bytes = ScaleBytes(as_bytes)
- rpc_runtime_config = RuntimeConfiguration()
- rpc_runtime_config.update_type_registry(load_type_registry_preset("legacy"))
- rpc_runtime_config.update_type_registry(custom_rpc_type_registry)
-
- type_string = type_name.name
-
- if is_option:
- type_string = f'Option<{type_string}>'
- if is_vec:
- type_string = f'Vec<{type_string}>'
-
- obj = rpc_runtime_config.create_scale_object(
- type_string,
- data=as_scale_bytes
- )
-
- return obj.decode()
-
-# Dataclasses for chain data.
-@dataclass
-class ModuleInfo:
- r"""
- Dataclass for module metadata.
- """
- key: str
- uid: int
- netuid: int
- active: int
- # mapping of coldkey to amount staked to this Module
- stake: Dict[str, Balance]
- rank: float
- emission: float
- incentive: float
- dividends: float
- last_update: int
- weights: List[List[int]]
- bonds: List[List[int]]
- pruning_score : int = 0
-
- @classmethod
- def fix_decoded_values(cls, module_info_decoded: Any) -> 'ModuleInfo':
- r""" Fixes the values of the ModuleInfo object.
- """
- module_info_decoded['key'] = ss58_encode(module_info_decoded['key'], commune.modules.subspace.__ss58_format__)
- module_info_decoded['stake'] = { ss58_encode( key, commune.__ss58_format__): commune.modules.subspace.Balance.from_nano(int(stake)) for key, stake in module_info_decoded['stake'] }
- module_info_decoded['weights'] = [[int(weight[0]), int(weight[1])] for weight in module_info_decoded['weights']]
- module_info_decoded['bonds'] = [[int(bond[0]), int(bond[1])] for bond in module_info_decoded['bonds']]
- module_info_decoded['rank'] = commune.modules.subspace.utils.U16_NORMALIZED_FLOAT(module_info_decoded['rank'])
- module_info_decoded['emission'] = module_info_decoded['emission'] / NANOPERTOKEN
- module_info_decoded['incentive'] = commune.modules.subspace.utils.U16_NORMALIZED_FLOAT(module_info_decoded['incentive'])
- module_info_decoded['dividends'] = commune.modules.subspace.utils.U16_NORMALIZED_FLOAT(module_info_decoded['dividends'])
-
-
- return cls(**module_info_decoded)
-
- @classmethod
- def from_vec_u8(cls, vec_u8: List[int]) -> 'ModuleInfo':
- r""" Returns a ModuleInfo object from a vec_u8.
- """
- if len(vec_u8) == 0:
- return ModuleInfo._null_module()
-
- decoded = from_scale_encoding(vec_u8, ChainDataType.ModuleInfo)
- if decoded is None:
- return ModuleInfo._null_module()
-
- decoded = ModuleInfo.fix_decoded_values(decoded)
-
- return decoded
-
- @classmethod
- def list_from_vec_u8(cls, vec_u8: List[int]) -> List['ModuleInfo']:
- r""" Returns a list of ModuleInfo objects from a vec_u8.
- """
-
- decoded_list = from_scale_encoding(vec_u8, ChainDataType.ModuleInfo, is_vec=True)
- if decoded_list is None:
- return []
-
- decoded_list = [ModuleInfo.fix_decoded_values(decoded) for decoded in decoded_list]
- return decoded_list
-
-
- @staticmethod
- def _null_module() -> 'ModuleInfo':
- module = ModuleInfo(
- uid = 0,
- netuid = 0,
- active = 0,
- stake = {},
- # total_stake = Balance.from_nano(0),
- rank = 0,
- emission = 0,
- incentive = 0,
- dividends = 0,
- last_update = 0,
- weights = [],
- bonds = [],
- key = "000000000000000000000000000000000000000000000000",
- pruning_score = 0,
- )
- return module
-
- @staticmethod
- def _module_dict_to_namespace(module_dict) -> 'ModuleInfo':
- module = ModuleInfo( **module_dict )
- module.stake = { k: Balance.from_nano(stake) for k, stake in module.stake.items() }
- # module.total_stake = Balance.from_nano(module.total_stake)
- module.rank = module.rank / U16_MAX
- module.incentive = module.incentive / U16_MAX
- module.dividends = module.dividends / U16_MAX
- module.emission = module.emission / NANOPERTOKEN
- return module
-
-@dataclass
-class SubnetInfo:
- r"""
- Dataclass for subnet info.
- """
- netuid: int
- immunity_period: int
- min_allowed_weights: int
- max_weight_limit: float
- subnetwork_n: int
- max_n: int
- blocks_since_epoch: int
- tempo: int
- # netuid -> topk percentile prunning score requirement (u16:MAX normalized.)
- emission_value: float
-
- @classmethod
- def from_vec_u8(cls, vec_u8: List[int]) -> Optional['SubnetInfo']:
- r""" Returns a SubnetInfo object from a vec_u8.
- """
- if len(vec_u8) == 0:
- return None
-
- decoded = from_scale_encoding(vec_u8, ChainDataType.SubnetInfo)
-
- if decoded is None:
- return None
-
- return SubnetInfo.fix_decoded_values(decoded)
-
- @classmethod
- def list_from_vec_u8(cls, vec_u8: List[int]) -> List['SubnetInfo']:
- r""" Returns a list of SubnetInfo objects from a vec_u8.
- """
- decoded = from_scale_encoding(vec_u8, ChainDataType.SubnetInfo, is_vec=True, is_option=True)
-
- if decoded is None:
- return []
-
- decoded = [SubnetInfo.fix_decoded_values(d) for d in decoded]
-
- return decoded
-
- @classmethod
- def fix_decoded_values(cls, decoded: Dict) -> 'SubnetInfo':
- r""" Returns a SubnetInfo object from a decoded SubnetInfo dictionary.
- """
- return SubnetInfo(
- netuid = decoded['netuid'],
- immunity_period = decoded['immunity_period'],
- min_allowed_weights = decoded['min_allowed_weights'],
- max_weight_limit = decoded['max_weights_limit'],
- subnetwork_n = decoded['subnetwork_n'],
- max_n = decoded['max_allowed_uids'],
- blocks_since_epoch = decoded['blocks_since_last_step'],
- tempo = decoded['tempo'],
- emission_value= decoded['emission_values'],
- )
-
- def to_parameter_dict( self ) -> 'torch.nn.ParameterDict':
- r""" Returns a torch tensor of the subnet info.
- """
- return torch.nn.ParameterDict(
- self.__dict__
- )
-
- @classmethod
- def from_parameter_dict( cls, parameter_dict: 'torch.nn.ParameterDict' ) -> 'SubnetInfo':
- r""" Returns a SubnetInfo object from a torch parameter_dict.
- """
- return cls( **dict(parameter_dict) )
diff --git a/commune/modules/subspace/dashboard/subspace_dashboard.py b/commune/modules/subspace/dashboard/subspace_dashboard.py
deleted file mode 100644
index ab67c4e4a..000000000
--- a/commune/modules/subspace/dashboard/subspace_dashboard.py
+++ /dev/null
@@ -1,437 +0,0 @@
-import commune as c
-import streamlit as st
-import pandas as pd
-from streamlit.components.v1 import components
-import plotly.express as px
-
-
-class SubspaceDashboard(c.Module):
-
- def __init__(self, netuid = 0, network = 'main'):
- self.st = c.module('streamlit')()
- st.set_page_config(layout="wide")
- self.st = c.module('streamlit')()
- self.st.load_style()
- self.set_config(config=config)
- self.load_state(sync=False)
- self.key = c.get_key()
-
- self.st = c.module('streamlit')()
-
-
- def sync(self):
- return self.load_state(sync=True)
-
-
- def load_state(self, sync:bool=False, netuid=0, network='main'):
-
- t = c.timer()
-
- self.subspace = c.module('subspace')()
- self.state = self.subspace.state_dict()
- c.print(f'Loaded State in {t.seconds} seconds')
- self.netuid = self.netuid
- self.subnets = self.state['subnets']
-
- self.subnet2info = {s['netuid']: s for s in self.subnets}
- self.subnet2netuid = {s['name']: s['netuid'] for s in self.subnets}
- self.subnet_names = [s['name'] for s in self.subnets]
-
- self.modules = self.state['modules'][self.netuid]
- self.validators = [m for m in self.modules if m['name'].startswith('vali') ]
- self.keys = c.keys()
- self.key2index = {k:i for i,k in enumerate(self.keys)}
-
- self.subnet = self.subnet_names[0]
- self.namespace = {m['name']: m['address'] for m in self.modules}
- self.module_names = [m['name'] for m in self.modules]
- self.subnet_info = self.subnet2info[self.netuid]
- self.block = self.state['block']
-
-
-
- def select_key(self,):
- with st.expander('Select Key', expanded=True):
- key = 'module'
- key = st.selectbox('Select Key', self.keys, index=self.key2index[key])
- self.key = c.get_key(key)
- if self.key.path == None:
- self.key.path = key
- self.key_info_dict = self.subspace.key_info(self.key.path, fmt='j')
-
- st.write('Address: ', self.key.ss58_address)
- st.write('Stake', self.key_info_dict.get('stake', 0))
- st.write('Balance', self.key_info_dict.get('balance', 0))
-
- def create_key(self):
- with st.expander('Create Key', expanded=False):
- new_key = st.text_input('Name of Key', '', key='create')
- create_key_button = st.button('Create Key')
- if create_key_button and len(new_key) > 0:
- c.add_key(new_key)
- key = c.get_key(new_key)
-
- def rename_key(self):
- with st.expander('Rename Key', expanded=False):
- old_key = st.selectbox('Select Key', self.keys, index=self.key2index[self.key.path], key='select old rename key')
- new_key = st.text_input('New of Key', '', key='rename')
- rename_key_button = st.button('Rename Key')
- replace_key = st.checkbox('Replace Key')
- if rename_key_button and len(new_key) > 0:
- if c.key_exists(new_key) and not replace_key:
- st.error('Key already exists')
- c.rename_key(old_key,new_key)
- key = c.get_key(new_key)
-
- def remove_key(self):
- with st.form(key='Remove Key'):
- rm_keys = st.multiselect('Select Key(s) to Remove', self.keys, [], key='rm_key')
- rm_key_button = st.form_submit_button('Remove Key')
- if rm_key_button:
- c.rm_keys(rm_keys)
-
- def key_dashboard(self):
- # self.select_key()
- self.create_key()
- self.rename_key()
- self.remove_key()
-
- def subnet_management(self):
- with st.expander('Subnet', expanded=True):
-
- subnets = self.subspace.subnets()
- if len(subnets) == 0:
- subnets = [self.default_subnet]
- else:
- subnets = [n['name'] for n in subnets]
- subnet2index = {n:i for i,n in enumerate(subnets)}
- subnet = st.selectbox('Subnet', subnets, index=subnet2index['commune'])
- self.netuid = self.subspace.subnet2netuid(subnet)
-
- def sidebar(self):
- with st.sidebar:
- st.write('# commune')
- key2index = {k:i for i,k in enumerate(self.keys)}
- st.write('## Select Subnet')
- self.subnet = st.selectbox(' ', self.subnet_names, 0, key='Select Subnet')
- self.netuid = self.subnet2netuid[self.subnet]
- sync = st.button('Sync')
- if sync:
- self.sync()
-
- self.select_key()
-
- def get_module_stats(self, modules):
- df = pd.DataFrame(modules)
- del_keys = ['stake_from', 'stake_to', 'key']
- for k in del_keys:
- del df[k]
- return df
-
- # for k in ['emission', 'stake']:
- # df[k] = df[k].apply(lambda x: c.round_decimals(self.subspace.format_amount(x, fmt='j'), 2))
-
- # df.sort_values('incentive', inplace=True, ascending=False)
- # df = df[:max_rows]
- # st.write(df)
- # st.dataframe(df, width=1000)
- # # BAR OF INCENTIVES
- # options = ['emission', 'incentive', 'dividends']
- # selected_keys = st.multiselect('Select Columns', options, options, key='stats')
-
- # for i, k in enumerate(selected_keys):
- # cols = st.columns(2)
-
- # fig = px.line(df, y=k, x= 'name', title=f'{k.upper()} Per Module')
- # cols[0].plotly_chart(fig)
- # fig = px.histogram(df, y=k, title=f'{k.upper()} Distribution')
- # cols[1].plotly_chart(fig)
-
-
- @classmethod
- def dashboard(cls, key = None):
- import streamlit as st
- # plotly
- self = cls()
- self.sidebar()
-
- tabs = st.tabs(['Modules', 'Validators', 'Wallet'])
- with tabs[0]:
- self.modules_dashboard()
- with tabs[1]:
- self.validator_dashboard()
- with tabs[2]:
- self.wallet_dashboard()
- # with tabs[4]:
- # self.key_dashboard()
-
- def subnet_dashboard(self):
- st.write('# Subnet')
- df = pd.DataFrame(self.subnets)
-
- if len(df) > 0:
- fig = px.pie(df, values='stake', names='name', title='Subnet Balances')
- st.plotly_chart(fig)
-
- for subnet in self.subnets:
- subnet = subnet.pop('name', None)
- with st.expander(subnet, expanded=True):
- st.write(subnet)
-
- # convert into metrics
-
- def transfer_dashboard(self):
- with st.expander('Transfer', expanded=True):
- amount = st.number_input('amount', 0.0, 10000000.0, 0.0, 0.1)
- to_address = st.text_input('dest', '')
- transfer_button = st.button('Transfer')
- if transfer_button:
- kwargs = {
- 'dest': to_address,
- 'amount': amount,
- 'key': self.key,
- }
- self.subspace.transfer(**kwargs)
-
- def staking_dashboard(self):
- cols = st.columns(2)
- with cols[0].expander('Stake', expanded=True):
-
- amount = st.number_input('STAKE Amount', 0.0, float(self.key_info_dict['balance']), float(self.key_info_dict['balance']), 0.1)
- modules = st.multiselect('Module', self.module_names, [])
- transfer_button = st.button('STAKE')
-
- if transfer_button:
-
-
- for m in modules:
- kwargs = {
- 'amount': amount,
- 'module_key': m,
- 'key': self.key,
- }
-
- self.subspace.stake(**kwargs)
-
- with cols[1].expander('UnStake', expanded=True):
- module2stake_from_key = self.subspace.get_staked_modules(self.key, fmt='j')
- modules = list(module2stake_from_key.keys())
- module = st.selectbox('Module', modules, index=0, key='unstake')
- module_to_stake = module2stake_from_key[module]
- amount = st.number_input('UNSTAKE Amount', 0.0, float(module_to_stake), float(module_to_stake), 1.0)
-
- unstake_button = st.button('UNSTAKE')
- if unstake_button:
- kwargs = {
- 'amount': amount,
- 'module_key': module,
- 'key': self.key,
- }
- self.subspace.unstake(**kwargs)
-
-
-
- def playground_dashboard(self):
- st.write('# Playground')
-
- def register_dashboard(self):
-
- df = pd.DataFrame(self.modules)
-
- with st.expander('Register Module', expanded=True):
- self.launch_dashboard()
-
- with st.expander('Modules', expanded=False):
- st.write(self.modules)
-
- # pie of stake per module
- # select fields to show
-
- if len(df)> 0:
- with st.expander('Module Statistics', expanded=False):
- value_field2index = {v:i for i,v in enumerate(list(df.columns))}
- key_field2index = {v:i for i,v in enumerate(list(df.columns))}
- value_field = st.selectbox('Value Field', df.columns , index=value_field2index['stake'])
- key_field = st.selectbox('Key Field',df.columns, index=value_field2index['name'])
-
- # plot pie chart in a funky color
-
- fig = px.pie(df, values=value_field, names=key_field, title='Module Balances', color_discrete_sequence=px.colors.sequential.RdBu)
- # show the key field
- # do it in funky way
-
- st.plotly_chart(fig)
- st.write(df)
-
- def modules_dashboard(self):
- # self.launch_dashboard(expanded=False)
- netuid = 0
- st.write('# Modules')
- for m in self.modules:
- m['delegate_stake'] = sum([s[1] for s in m['stake_from'][1:]])
- # m['address'] = m['address'].split(':')[0]
- for k in ['balance', 'stake', 'delegate_stake', 'emission']:
- m[k] = m[k]/1e9
- for del_k in ['key', 'stake_from', 'stake_to']:
- del m[del_k]
- df = pd.DataFrame(self.modules)
- df.sort_values('emission', inplace=True, ascending=False)
- df.reset_index(inplace=True)
-
- stats = {
- 'total_stake': sum(df['stake']),
- 'total_emission': sum(df['emission']),
- 'total_balance': sum(df['balance']),
- 'total_delegate_stake': sum(df['delegate_stake']),
- 'block': self.block,
-
- }
-
- # make df hit the edge of the screen
- st.write(df)
-
- # make a pie chart of the stake
- self.st.metrics_dict(stats, num_rows=1)
-
- with st.expander('Plot', expanded=False):
- self.st.run(df)
-
-
-
- def archive_dashboard(self):
- # self.launch_dashboard(expanded=False)
- netuid = 0
- df = self.get_module_stats(self.modules)
- archive_history = self.subspace.archive_history(lookback_hours=24, n=100, update=True)
- df = c.df(archive_history[1:])
- df['block'] = df['block'].astype(int)
-
-
- df['dt'] = pd.to_datetime(df['dt'])
- df.sort_values('block', inplace=True)
- df.reset_index(inplace=True)
- st.write(df)
- # df= df[df['market_cap'] < 1e9]
-
-
- fig = px.line(df, x='block', y='market_cap', title='Archive History')
-
- block2path= {b:df['path'][i] for i,b in enumerate(df['block'])}
- blocks = list(block2path.keys())
- paths = list(block2path.values())
- block = st.selectbox('Block', blocks, index=0)
- path = block2path[block]
- state = c.get(path)
- st.write(state.keys())
- modules = state['modules'][netuid]
- for i in range(len(modules)):
- for k in ['stake_to', 'stake_from', 'key', 'address']:
- del modules[i][k]
- for k in ['emission', 'stake', 'balance']:
- modules[i][k] = modules[i][k]/1e9
- df = pd.DataFrame(modules)
-
- st.write(df)
- subnet_df = pd.DataFrame(state['subnets'])
- st.write(subnet_df)
- # st.write(state)
-
-
-
- st.write(fig)
- # options = ['emission', 'incentive', 'dividends', 'stake']
- # y = st.selectbox('Select Columns', options, 0)
- # # filter by stake > 1000
-
- # df = df[df['stake'] > 10**9]
- # histogram = px.histogram(df, x=y, title='My Modules')
-
- # st.write(histogram)
-
- def wallet_dashboard(self):
- st.write('# Wallet')
- self.launch_dashboard()
- # if self.subspace.is_registered(self.key):
- # self.staking_dashboard()
- # self.transfer_dashboard()
- # else:
- # # with emoji
- # st.error('Please Register Your Key')
-
- def validator_dashboard(self):
- validators = [{k:v[k] for k in c.copy(list(v.keys())) if k != 'stake_from'} for v in self.validators if v['stake'] > 0]
- # df = c.df(validators)
- # if len(df) == 0:
- # st.error('No Validators')
- # return
-
- # df['stake'] = df['stake']/1e9
- # df['emission'] = df['emission']/1e9
- # st.dataframe(df)
- # with st.expander('Register Validator', expanded=False):
- # self.launch_dashboard(expanded=False, prefix='vali')
-
-
- def launch_dashboard(self, expanded=True, prefix= None ):
- modules = c.modules(prefix)
- module2idx = {m:i for i,m in enumerate(modules)}
-
- self.st.line_seperator()
-
- cols = st.columns([3,1, 6])
-
-
-
- with cols[0]:
- module = st.selectbox('Select A Module', modules, 0)
- tag = self.subspace.resolve_unique_server_name(module, tag=None ).replace(f'{module}::', '')
- subnet = st.text_input('subnet', self.config.subnet, key=f'subnet.{prefix}')
- tag = st.text_input('tag', tag, key=f'tag.{prefix}')
- # n = st.slider('replicas', 1, 10, 1, 1, key=f'n.{prefix}')
- serve = st.checkbox('serve', True, key=f'serve.{prefix}')
-
- register = st.button('Register', key=f'register.{prefix}')
-
-
- with cols[-1]:
- st.write(f'#### {module.upper()} Kwargs ')
-
- fn_schema = c.fn_schema(c.module(module), '__init__')
- kwargs = self.st.function2streamlit(module=module, fn='__init__' )
-
- kwargs = self.st.process_kwargs(kwargs, fn_schema)
- self.st.line_seperator()
-
- n = 1
-
- if 'None' == tag:
- tag = None
-
-
- if 'tag' in kwargs:
- kwargs['tag'] = tag
-
- if register:
- try:
- if n > 1:
- tags = [f'{tag}.{i}' if tag != None else str(i) for i in range(n)]
- else:
- tags = [tag]
-
- for tag in tags:
- response = self.register(module=module,
- tag=tag,
- subnet=subnet,
- kwargs=kwargs,
- network=self.network,
- serve=serve)
- except Exception as e:
- response = {'success': False, 'message': str(e)}
- if response['success']:
- st.success('Module Registered')
- else:
- st.error(response['message'])
-
-
-
-
diff --git a/commune/modules/subspace/subspace.py b/commune/modules/subspace/subspace.py
deleted file mode 100644
index de8d4aef8..000000000
--- a/commune/modules/subspace/subspace.py
+++ /dev/null
@@ -1,3991 +0,0 @@
-
-import torch
-import scalecodec
-from retry import retry
-from typing import List, Dict, Union, Optional, Tuple
-from substrateinterface import SubstrateInterface
-from typing import List, Dict, Union, Optional, Tuple
-from commune.utils.network import ip_to_int, int_to_ip
-from rich.prompt import Confirm
-from commune.modules.subspace.balance import Balance
-from commune.modules.subspace.utils import (U16_NORMALIZED_FLOAT,
- U64_MAX,
- NANOPERTOKEN,
- U16_MAX,
- is_valid_address_or_public_key,
- )
-from commune.modules.subspace.chain_data import (ModuleInfo, custom_rpc_type_registry)
-
-import streamlit as st
-import json
-from loguru import logger
-import os
-import commune as c
-
-logger = logger.opt(colors=True)
-
-
-
-class Subspace(c.Module):
- """
- Handles interactions with the subspace chain.
- """
- fmt = 'j'
- whitelist = []
- chain_name = 'subspace'
- default_config = c.get_config(chain_name, to_munch=False)
- token_decimals = default_config['token_decimals']
- network = default_config['network']
- chain = network
- libpath = chain_path = c.libpath + '/subspace'
- spec_path = f"{chain_path}/specs"
- netuid = default_config['netuid']
- image = 'vivonasg/subspace:latest'
- mode = 'docker'
-
- def __init__(
- self,
- url: str = None,
- network: str = network,
- local:bool = False,
- **kwargs,
- ):
- config = self.set_config(kwargs=locals())
- if config.loop:
- c.thread(self.loop)
-
- def set_network(self,
- network:str = network,
- url : str = None,
- websocket:str=None,
- ss58_format:int=42,
- type_registry:dict=custom_rpc_type_registry,
- type_registry_preset=None,
- cache_region=None,
- runtime_config=None,
- use_remote_preset=False,
- ws_options=None,
- auto_discover=True,
- auto_reconnect=True,
- verbose:bool=False,
- max_trials:int = 10,
- **kwargs):
-
- '''
- A specialized class in interfacing with a Substrate node.
-
- Parameters
- A specialized class in interfacing with a Substrate node.
-
- Parameters
- url : the URL to the substrate node, either in format or wss://127.0.0.1:9944
-
- ss58_format : The address type which account IDs will be SS58-encoded to Substrate addresses. Defaults to 42, for Kusama the address type is 2
-
- type_registry : A dict containing the custom type registry in format: {'types': {'customType': 'u32'},..}
-
- type_registry_preset : The name of the predefined type registry shipped with the SCALE-codec, e.g. kusama
-
- cache_region : a Dogpile cache region as a central store for the metadata cache
-
- use_remote_preset : When True preset is downloaded from Github master, otherwise use files from local installed scalecodec package
-
- ws_options : dict of options to pass to the websocket-client create_connection function
- : dict of options to pass to the websocket-client create_connection function
-
- '''
-
- from substrateinterface import SubstrateInterface
-
- if network == None:
- network = self.config.network
-
- trials = 0
- while trials < max_trials :
- trials += 1
- url = self.resolve_node_url(url=url, chain=network, local=self.config.local)
- c.print(f'Connecting to {url}...')
- ip = c.ip()
- url = url.replace(ip, '0.0.0.0')
-
- kwargs.update(url=url,
- websocket=websocket,
- ss58_format=ss58_format,
- type_registry=type_registry,
- type_registry_preset=type_registry_preset,
- cache_region=cache_region,
- runtime_config=runtime_config,
- ws_options=ws_options,
- auto_discover=auto_discover,
- auto_reconnect=auto_reconnect)
- try:
- self.substrate= SubstrateInterface(**kwargs)
- break
- except Exception as e:
- c.print(e, url)
- self.config.local = False
- url = None
-
- self.url = url
- self.network = network
- response = {'success': True, 'message': f'Connected to {url}', 'network': network, 'url': url}
-
- return response
- def __repr__(self) -> str:
- return f''
- def __str__(self) -> str:
- return f' |