tumblrbot 1.6.0__tar.gz → 1.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tumblrbot
3
- Version: 1.6.0
3
+ Version: 1.7.0
4
4
  Summary: An updated bot that posts to Tumblr, based on your very own blog!
5
5
  Requires-Python: >= 3.13
6
6
  Description-Content-Type: text/markdown
@@ -36,6 +36,8 @@ Project-URL: Source, https://github.com/MaidScientistIzutsumiMarin/tumblrbot
36
36
 
37
37
  [Tumblr]: https://tumblr.com
38
38
  [Tumblr Tokens]: https://tumblr.com/oauth/apps
39
+ [Tumblr API Documentation on Blog Identifiers]: https://tumblr.com/docs/en/api/v2#blog-identifiers
40
+ [Tumblr API Documentation on Rate Limits]: https://tumblr.com/docs/en/api/v2#rate-limits
39
41
 
40
42
  [Download]: src/tumblrbot/flow/download.py
41
43
  [Examples]: src/tumblrbot/flow/examples.py
@@ -58,7 +60,7 @@ Features:
58
60
  1. Asks for [OpenAI] and [Tumblr] tokens.
59
61
  - Stores API tokens using [keyring].
60
62
  1. Retrieves [Tumblr] [OAuth] tokens.
61
- 1. [Downloads posts][Download] from the [configured][config] [Tumblr] blogs.
63
+ 1. [Downloads posts][Download] from the [configured][config] blogs.
62
64
  - Skips redownloading already downloaded posts.
63
65
  - Shows progress and previews the current post.
64
66
  1. [Creates examples][Examples] to fine-tune the model from your posts.
@@ -70,22 +72,24 @@ Features:
70
72
  - Resumes monitoring the same fine-tuning process when restarted.
71
73
  - Deletes the uploaded examples file if fine-tuning does not succeed (optional).
72
74
  - Stores the output model automatically when fine-tuning is completed.
73
- 1. [Generates and uploads posts][Generate] to the [configured][config] [Tumblr] blog using the [configured][config] fine-tuned model.
75
+ 1. [Generates and uploads posts][Generate] to the [configured][config] blog using the [configured][config] fine-tuned model.
74
76
  - Creates tags by extracting keywords at the [configured][config] frequency using the [configured][config] model.
75
- - Uploads posts as drafts to the [configured][config] [Tumblr] blog.
76
- - Reblog posts at the [configured][config] frequency.
77
+ - Uploads posts as drafts to the [configured][config] blog.
78
+ - Reblogs posts from the [configured][config] blogs at the [configured][config] frequency.
77
79
  - Shows progress and previews the current post.
78
80
  - Colorful output, progress bars, and post previews using [rich].
79
81
  - Automatically keeps the [config] file up-to-date and recreates it if missing.
80
82
 
81
83
  **To-Do:**
82
84
 
83
- - ...
85
+ - Create training data from a sample of posts (possible).
86
+ - User-specified list of words that will filter out posts.
84
87
 
85
88
  **Known Issues:**
86
89
 
87
90
  - Sometimes, you will get an error about the training file not being found when starting fine-tuning. We do not currently have a fix or workaround for this. You should instead use the online portal for fine-tuning if this continues to happen. Read more in [fine-tuning].
88
91
  - Post counts are incorrect when downloading posts. We are not certain what the cause of this is, but our tests suggest this is a [Tumblr] API problem that is giving inaccurate numbers.
92
+ - During post downloading or post generation, you may receive a "Limit Exceeded" error message from the [Tumblr] API. This is caused by server-side rate-limiting by [Tumblr]. The only workaround is trying again or waiting for a period of time before retrying. In most cases, you either have to wait for a minute or an hour for the limits to reset. You can read more about the limits in the [Tumblr API documentation on rate limits].
89
93
 
90
94
  **Please submit an issue or contact us for features you want added/reimplemented.**
91
95
 
@@ -137,6 +141,10 @@ All config options can be found in `config.toml` after running the program once.
137
141
 
138
142
  All file options can include directories that will be created when the program is run.
139
143
 
144
+ All config options that involve *blog identifiers* expect any version of a blog URL, which is explained in more detail in the [Tumblr API documentation on blog identifiers].
145
+
146
+ Specific Options:
147
+
140
148
  - `custom_prompts_file` This file should follow the following file format:
141
149
 
142
150
  ```json
@@ -148,13 +156,15 @@ All file options can include directories that will be created when the program i
148
156
  To be specific, it should follow the [JSON Lines] file format with one collection of name/value pairs (a dictionary) per line. You can validate your file using the [JSON Lines Validator].
149
157
 
150
158
  - **`developer_message`** - This message is used in for fine-tuning the AI as well as generating prompts. If you change this, you will need to run the fine-tuning again with the new value before generating posts.
151
- - **`user_message`** - This message is used in the same way as `developer_message` and should be treated the same.
159
+ - **`user_message`** - This setting is used and works in the same way as `developer_message`.
152
160
  - **`expected_epochs`** - The default value here is the default number of epochs for `base_model`. You may have to change this value if you change `base_model`. After running fine-tuning once, you will see the number of epochs used in the [fine-tuning portal] under *Hyperparameters*. This value will also be updated automatically if you run fine-tuning through this program.
153
161
  - **`token_price`** - The default value here is the default token price for `base_model`. You can find the up-to-date value in [OpenAI Pricing], in the *Training* column.
154
162
  - **`job_id`** - If there is any value here, this program will resume monitoring the corresponding job, instead of starting a new one. This gets set when starting the fine-tuning and is cleared when it is completed. You can read more in [fine-tuning].
155
163
  - **`base_model`** - This value is used to choose the tokenizer for estimating fine-tuning costs. It is also the base model that will be fine-tuned and the model that is used to generate tags. You can find a list of options in the [fine-tuning portal] by pressing `+ Create` and opening the drop-down list for `Base Model`. Be sure to update `token_price` if you change this value.
156
164
  - **`fine_tuned_model`** - Set automatically after monitoring fine-tuning if the job has succeeded. You can read more in [fine-tuning].
157
165
  - **`tags_chance`** - This should be between 0 and 1. Setting it to 0 corresponds to a 0% chance (never) to add tags to a post. 1 corresponds to a 100% chance (always) to add tags to a post. Adding tags incurs a very small token cost.
166
+ - **`reblog_chance`** - This setting works the same way as `tags_chance`.
167
+ - **`reblog_user_message`** - This setting is a prefix that is directly prepended to the contents of the post being reblogged.
158
168
 
159
169
  ## Manual Fine-Tuning
160
170
 
@@ -18,6 +18,8 @@
18
18
 
19
19
  [Tumblr]: https://tumblr.com
20
20
  [Tumblr Tokens]: https://tumblr.com/oauth/apps
21
+ [Tumblr API Documentation on Blog Identifiers]: https://tumblr.com/docs/en/api/v2#blog-identifiers
22
+ [Tumblr API Documentation on Rate Limits]: https://tumblr.com/docs/en/api/v2#rate-limits
21
23
 
22
24
  [Download]: src/tumblrbot/flow/download.py
23
25
  [Examples]: src/tumblrbot/flow/examples.py
@@ -40,7 +42,7 @@ Features:
40
42
  1. Asks for [OpenAI] and [Tumblr] tokens.
41
43
  - Stores API tokens using [keyring].
42
44
  1. Retrieves [Tumblr] [OAuth] tokens.
43
- 1. [Downloads posts][Download] from the [configured][config] [Tumblr] blogs.
45
+ 1. [Downloads posts][Download] from the [configured][config] blogs.
44
46
  - Skips redownloading already downloaded posts.
45
47
  - Shows progress and previews the current post.
46
48
  1. [Creates examples][Examples] to fine-tune the model from your posts.
@@ -52,22 +54,24 @@ Features:
52
54
  - Resumes monitoring the same fine-tuning process when restarted.
53
55
  - Deletes the uploaded examples file if fine-tuning does not succeed (optional).
54
56
  - Stores the output model automatically when fine-tuning is completed.
55
- 1. [Generates and uploads posts][Generate] to the [configured][config] [Tumblr] blog using the [configured][config] fine-tuned model.
57
+ 1. [Generates and uploads posts][Generate] to the [configured][config] blog using the [configured][config] fine-tuned model.
56
58
  - Creates tags by extracting keywords at the [configured][config] frequency using the [configured][config] model.
57
- - Uploads posts as drafts to the [configured][config] [Tumblr] blog.
58
- - Reblog posts at the [configured][config] frequency.
59
+ - Uploads posts as drafts to the [configured][config] blog.
60
+ - Reblogs posts from the [configured][config] blogs at the [configured][config] frequency.
59
61
  - Shows progress and previews the current post.
60
62
  - Colorful output, progress bars, and post previews using [rich].
61
63
  - Automatically keeps the [config] file up-to-date and recreates it if missing.
62
64
 
63
65
  **To-Do:**
64
66
 
65
- - ...
67
+ - Create training data from a sample of posts (possible).
68
+ - User-specified list of words that will filter out posts.
66
69
 
67
70
  **Known Issues:**
68
71
 
69
72
  - Sometimes, you will get an error about the training file not being found when starting fine-tuning. We do not currently have a fix or workaround for this. You should instead use the online portal for fine-tuning if this continues to happen. Read more in [fine-tuning].
70
73
  - Post counts are incorrect when downloading posts. We are not certain what the cause of this is, but our tests suggest this is a [Tumblr] API problem that is giving inaccurate numbers.
74
+ - During post downloading or post generation, you may receive a "Limit Exceeded" error message from the [Tumblr] API. This is caused by server-side rate-limiting by [Tumblr]. The only workaround is trying again or waiting for a period of time before retrying. In most cases, you either have to wait for a minute or an hour for the limits to reset. You can read more about the limits in the [Tumblr API documentation on rate limits].
71
75
 
72
76
  **Please submit an issue or contact us for features you want added/reimplemented.**
73
77
 
@@ -119,6 +123,10 @@ All config options can be found in `config.toml` after running the program once.
119
123
 
120
124
  All file options can include directories that will be created when the program is run.
121
125
 
126
+ All config options that involve *blog identifiers* expect any version of a blog URL, which is explained in more detail in the [Tumblr API documentation on blog identifiers].
127
+
128
+ Specific Options:
129
+
122
130
  - `custom_prompts_file` This file should follow the following file format:
123
131
 
124
132
  ```json
@@ -130,13 +138,15 @@ All file options can include directories that will be created when the program i
130
138
  To be specific, it should follow the [JSON Lines] file format with one collection of name/value pairs (a dictionary) per line. You can validate your file using the [JSON Lines Validator].
131
139
 
132
140
  - **`developer_message`** - This message is used in for fine-tuning the AI as well as generating prompts. If you change this, you will need to run the fine-tuning again with the new value before generating posts.
133
- - **`user_message`** - This message is used in the same way as `developer_message` and should be treated the same.
141
+ - **`user_message`** - This setting is used and works in the same way as `developer_message`.
134
142
  - **`expected_epochs`** - The default value here is the default number of epochs for `base_model`. You may have to change this value if you change `base_model`. After running fine-tuning once, you will see the number of epochs used in the [fine-tuning portal] under *Hyperparameters*. This value will also be updated automatically if you run fine-tuning through this program.
135
143
  - **`token_price`** - The default value here is the default token price for `base_model`. You can find the up-to-date value in [OpenAI Pricing], in the *Training* column.
136
144
  - **`job_id`** - If there is any value here, this program will resume monitoring the corresponding job, instead of starting a new one. This gets set when starting the fine-tuning and is cleared when it is completed. You can read more in [fine-tuning].
137
145
  - **`base_model`** - This value is used to choose the tokenizer for estimating fine-tuning costs. It is also the base model that will be fine-tuned and the model that is used to generate tags. You can find a list of options in the [fine-tuning portal] by pressing `+ Create` and opening the drop-down list for `Base Model`. Be sure to update `token_price` if you change this value.
138
146
  - **`fine_tuned_model`** - Set automatically after monitoring fine-tuning if the job has succeeded. You can read more in [fine-tuning].
139
147
  - **`tags_chance`** - This should be between 0 and 1. Setting it to 0 corresponds to a 0% chance (never) to add tags to a post. 1 corresponds to a 100% chance (always) to add tags to a post. Adding tags incurs a very small token cost.
148
+ - **`reblog_chance`** - This setting works the same way as `tags_chance`.
149
+ - **`reblog_user_message`** - This setting is a prefix that is directly prepended to the contents of the post being reblogged.
140
150
 
141
151
  ## Manual Fine-Tuning
142
152
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tumblrbot"
3
- version = "1.6.0"
3
+ version = "1.7.0"
4
4
  description = "An updated bot that posts to Tumblr, based on your very own blog!"
5
5
  readme = "README.md"
6
6
  requires-python = ">= 3.13"
@@ -1,4 +1,4 @@
1
- from random import random, randrange
1
+ from random import choice, random, randrange
2
2
  from typing import override
3
3
 
4
4
  import rich
@@ -28,7 +28,7 @@ class DraftGenerator(FlowClass):
28
28
  rich.print(f":chart_increasing: [bold green]Generated {self.config.draft_count} draft(s).[/] {message}")
29
29
 
30
30
  def generate_post(self) -> Post:
31
- if random() < self.config.reblog_chance: # noqa: S311
31
+ if self.config.reblog_blog_identifiers and random() < self.config.reblog_chance: # noqa: S311
32
32
  original = self.get_random_post()
33
33
  user_message = f"{self.config.reblog_user_message}\n\n{original.get_content_text()}"
34
34
  else:
@@ -66,9 +66,14 @@ class DraftGenerator(FlowClass):
66
66
  return None
67
67
 
68
68
  def get_random_post(self) -> Post:
69
- total = self.tumblr.retrieve_blog_info(self.config.upload_blog_identifier).response.blog.posts
70
- post = self.tumblr.retrieve_published_posts(
71
- self.config.upload_blog_identifier,
72
- offset=randrange(total), # noqa: S311
73
- ).response.posts[0]
74
- return Post.model_validate(post)
69
+ blog_identifier = choice(self.config.reblog_blog_identifiers) # noqa: S311
70
+ while True:
71
+ total = self.tumblr.retrieve_blog_info(blog_identifier).response.blog.posts
72
+ for raw_post in self.tumblr.retrieve_published_posts(
73
+ blog_identifier,
74
+ "text",
75
+ randrange(total), # noqa: S311
76
+ ).response.posts:
77
+ post = Post.model_validate(raw_post)
78
+ if post.valid_text_post():
79
+ return post
@@ -46,7 +46,7 @@ class Config(FileSyncSettings):
46
46
  toml_file: ClassVar = Path("config.toml")
47
47
 
48
48
  # Downloading Posts & Writing Examples
49
- download_blog_identifiers: list[str] = Field([], description="The identifiers of the blogs which post data will be downloaded from. These must be blogs associated with the same account as the configured Tumblr secret tokens.")
49
+ download_blog_identifiers: list[str] = Field([], description="The identifiers of the blogs which post data will be downloaded from.")
50
50
  data_directory: Path = Field(Path("data"), description="Where to store downloaded post data.")
51
51
 
52
52
  # Writing Examples
@@ -72,10 +72,11 @@ class Config(FileSyncSettings):
72
72
  # Generating
73
73
  upload_blog_identifier: str = Field("", description="The identifier of the blog which generated drafts will be uploaded to. This must be a blog associated with the same account as the configured Tumblr secret tokens.")
74
74
  draft_count: PositiveInt = Field(150, description="The number of drafts to process. This will affect the number of tokens used with OpenAI")
75
- tags_chance: NonNegativeFloat = Field(0.1, description="The chance to generate tags for any given post. This will incur extra calls to OpenAI.")
75
+ tags_chance: NonNegativeFloat = Field(0.1, description="The chance to generate tags for any given post. This will use more OpenAI tokens.")
76
76
  tags_developer_message: str = Field("You will be provided with a block of text, and your task is to extract a very short list of the most important subjects from it.", description="The developer message used to generate tags.")
77
- reblog_chance: NonNegativeFloat = Field(0.05, description="The chance to generate a reblog of a random post.")
78
- reblog_user_message: str = Field("Please write a comical Tumblr post in response to the following Tumblr post:", description="The prefix for the user message used to reblog posts.")
77
+ reblog_blog_identifiers: list[str] = Field([], description="The identifiers of blogs that can be reblogged from when generating drafts.")
78
+ reblog_chance: NonNegativeFloat = Field(0.05, description="The chance to generate a reblog of a random post. This will use more OpenAI tokens.")
79
+ reblog_user_message: str = Field("Please write a comical Tumblr post in response to the following post from your blog:", description="The prefix for the user message used to reblog posts.")
79
80
 
80
81
  @classmethod
81
82
  @override
@@ -1,4 +1,4 @@
1
- from typing import Self
1
+ from typing import Literal, Self
2
2
 
3
3
  from requests import HTTPError, Response
4
4
  from requests_oauthlib import OAuth1Session
@@ -26,10 +26,17 @@ class TumblrSession(OAuth1Session):
26
26
  response = self.get(f"https://api.tumblr.com/v2/blog/{blog_identifier}/info")
27
27
  return ResponseModel.model_validate_json(response.text)
28
28
 
29
- def retrieve_published_posts(self, blog_identifier: str, offset: int | None = None, after: int | None = None) -> ResponseModel:
29
+ def retrieve_published_posts(
30
+ self,
31
+ blog_identifier: str,
32
+ type_: Literal["text", "quote", "link", "answer", "video", "audio", "photo", "chat"] | None = None,
33
+ offset: int | None = None,
34
+ after: int | None = None,
35
+ ) -> ResponseModel:
30
36
  response = self.get(
31
37
  f"https://api.tumblr.com/v2/blog/{blog_identifier}/posts",
32
38
  params={
39
+ "type": type_,
33
40
  "offset": offset,
34
41
  "after": after,
35
42
  "sort": "asc",
File without changes
File without changes
File without changes